import { sleep } from '@/utils';
import { ApiError } from '@/lib/api/errors';
import type { PageParams, Paginated } from '@/lib/api/types';
import { resolveSeedCity, resolveSeedDistrict } from '@/services/geography/apis/seed';
import { SERVICE_AREAS_PAGE_SIZE } from '../constants';
import { areaExists, type AddServiceAreaInput, type NurseServiceArea, type ServiceAreasApi } from '../types';

const MOCK_LATENCY_MS = 300;

// In-memory store, seeded **empty** so the "won't appear in search" empty-state warning demos.
let store: NurseServiceArea[] = [];
let nextId = 1;

// Whole-city rows first (matching the contract's list order), then by most-recent add.
const ordered = () =>
  [...store].sort((a, b) => Number(b.isWholeCity) - Number(a.isWholeCity) || b.id - a.id);

function build(id: number, input: AddServiceAreaInput): NurseServiceArea {
  const city = resolveSeedCity(input.cityId);
  const districtId = input.districtId ?? null;
  const district = districtId == null ? undefined : resolveSeedDistrict(districtId);
  return {
    id,
    cityId: input.cityId,
    cityNameFa: city?.nameFa ?? '',
    cityNameEn: city?.nameEn ?? '',
    districtId,
    districtNameFa: district?.nameFa ?? null,
    districtNameEn: district?.nameEn ?? null,
    isWholeCity: districtId == null,
    isActive: true,
  };
}

/**
 * In-memory mock behind the ServiceAreasApi seam. Enforces the `UNIQUE(cityId, districtId)`
 * rule exactly as the server does — a duplicate (including a second whole-city row) throws the
 * same `409` the real endpoint returns — so the coverage editor's inline duplicate handling is
 * demonstrable end-to-end. Mirrors the real shapes for a one-line swap.
 */
export const serviceAreasMockApi: ServiceAreasApi = {
  list: async (params?: PageParams): Promise<Paginated<NurseServiceArea>> => {
    await sleep(MOCK_LATENCY_MS);
    const all = ordered();
    const page = params?.page ?? 1;
    const pageSize = params?.pageSize ?? SERVICE_AREAS_PAGE_SIZE;
    const start = (page - 1) * pageSize;
    return { items: all.slice(start, start + pageSize), total: all.length, page, pageSize };
  },

  add: async (input: AddServiceAreaInput): Promise<NurseServiceArea> => {
    await sleep(MOCK_LATENCY_MS);
    if (areaExists(store, input.cityId, input.districtId ?? null)) {
      throw new ApiError(409, 'Area already covered', 'area_duplicate');
    }
    const area = build(nextId++, input);
    store = [area, ...store];
    return area;
  },

  remove: async (id: number): Promise<void> => {
    await sleep(MOCK_LATENCY_MS);
    store = store.filter((area) => area.id !== id);
  },
};
