import { computed, ref } from 'vue';

import { getRegionList } from '#/views/system/region/api';

import type { RegionRow } from '../constants';
import {
  readRegionSelection,
  writeRegionSelection,
} from '../utils/regionSelectionStorage';

export function parseRegionListItems(items: Record<string, any>[]) {
  const level1: RegionRow[] = [];
  const level2Map: Record<number, RegionRow[]> = {};

  for (const item of items) {
    const row: RegionRow = {
      id: Number(item.id),
      name: String(item.name ?? ''),
      pid: Number(item.pid ?? 0),
      code: item.code,
      level: item.level,
      express_fee: item.express_fee,
      created_at: item.created_at,
    };

    if (Number(row.pid) === 0) {
      level1.push(row);
      continue;
    }

    const parentId = Number(row.pid);
    if (!level2Map[parentId]) {
      level2Map[parentId] = [];
    }
    level2Map[parentId].push(row);
  }

  level1.sort((a, b) => a.id - b.id);
  Object.values(level2Map).forEach((list) => list.sort((a, b) => a.id - b.id));

  return { level1, level2Map };
}

function restoreSelection(level1: RegionRow[], savedLevel1Id: number | null) {
  let level1Id = savedLevel1Id;
  if (!level1Id || !level1.some((item) => item.id === level1Id)) {
    level1Id = level1[0]?.id ?? null;
  }
  return { level1Id };
}

export function useRegionTree() {
  const saved = readRegionSelection();
  const loading = ref(false);
  const keyword = ref('');
  const level1List = ref<RegionRow[]>([]);
  const level2Map = ref<Record<number, RegionRow[]>>({});
  const selectedLevel1Id = ref<number | null>(saved.level1Id);

  const filteredLevel1 = computed(() => {
    const kw = keyword.value.trim().toLowerCase();
    if (!kw) {
      return level1List.value;
    }
    return level1List.value.filter((item) => {
      const children = level2Map.value[item.id] ?? [];
      if (item.name.toLowerCase().includes(kw)) {
        return true;
      }
      return children.some((child) => child.name.toLowerCase().includes(kw));
    });
  });

  const currentChildren = computed(() => {
    if (!selectedLevel1Id.value) {
      return [];
    }
    return level2Map.value[selectedLevel1Id.value] ?? [];
  });

  const selectedLevel1 = computed(() =>
    level1List.value.find((item) => item.id === selectedLevel1Id.value),
  );

  function persistSelection() {
    writeRegionSelection({
      level1Id: selectedLevel1Id.value,
    });
  }

  async function loadData() {
    loading.value = true;
    try {
      const res = await getRegionList({
        page: 1,
        pageSize: 500,
      });
      const items = res?.items ?? [];
      const parsed = parseRegionListItems(items);
      level1List.value = parsed.level1;
      level2Map.value = parsed.level2Map;

      const restored = restoreSelection(
        level1List.value,
        selectedLevel1Id.value,
      );
      selectedLevel1Id.value = restored.level1Id;
      persistSelection();
    } finally {
      loading.value = false;
    }
  }

  function selectLevel1(id: number) {
    selectedLevel1Id.value = id;
    persistSelection();
  }

  function patchRegion(id: number, patch: Partial<RegionRow>) {
    const inLevel1 = level1List.value.find((item) => item.id === id);
    if (inLevel1) {
      Object.assign(inLevel1, patch);
      return;
    }
    for (const list of Object.values(level2Map.value)) {
      const found = list.find((item) => item.id === id);
      if (found) {
        Object.assign(found, patch);
        if (patch.pid !== undefined && Number(patch.pid) !== Number(found.pid)) {
          loadData();
        }
        return;
      }
    }
  }

  return {
    currentChildren,
    filteredLevel1,
    keyword,
    level1List,
    level2Map,
    loadData,
    loading,
    patchRegion,
    selectLevel1,
    selectedLevel1,
    selectedLevel1Id,
  };
}
