import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { toast } from 'sonner';
import { api, ApiError, type ApiResponse } from '../lib/api';
import type {
  ClinicResource, ResourcePool, ResourcePayload, ResourceType, Skill,
} from '../types';

/**
 * منابع: هر چیزی که ممکن است اشغال باشد. هر منبع مال یک شعبه است، و شعبه همان
 * آدرس محل نوبت‌دهی است — پس فیلترها با `address_uuid` کار می‌کنند نه `branch_id`.
 */
const RESOURCES_KEY = 'resources';
const TYPES_KEY     = ['resource-types'];
const SKILLS_KEY    = ['skills'];
const POOLS_KEY     = ['resource-pools'];

function fail(e: unknown, fallback: string) {
  toast.error(e instanceof ApiError ? e.message : fallback);
}

export type ResourceFilters = {
  address_uuid?: string;
  type_uuid?: string;
  skill_uuid?: string;
  active?: string;
};

function toQuery(filters: ResourceFilters): string {
  const params = new URLSearchParams();
  Object.entries(filters).forEach(([k, v]) => {
    if (v) params.set(k, v);
  });
  const qs = params.toString();
  return qs === '' ? '' : `?${qs}`;
}

export function useResources(filters: ResourceFilters = {}) {
  const qc = useQueryClient();
  const invalidate = () => qc.invalidateQueries({ queryKey: [RESOURCES_KEY] });

  const query = useQuery({
    queryKey: [RESOURCES_KEY, filters],
    queryFn: () => api.get<ApiResponse<ClinicResource[]>>(`/api/v1/resources${toQuery(filters)}`),
  });

  const create = useMutation({
    mutationFn: (d: ResourcePayload) => api.post<ApiResponse<ClinicResource>>('/api/v1/resource', d),
    onSuccess: () => { toast.success('منبع افزوده شد'); invalidate(); },
    onError: (e) => fail(e, 'افزودن منبع ناموفق بود'),
  });

  const update = useMutation({
    mutationFn: ({ uuid, d }: { uuid: string; d: ResourcePayload }) =>
      api.patch<ApiResponse<ClinicResource>>(`/api/v1/resource/${uuid}`, d),
    onSuccess: () => { toast.success('منبع به‌روزرسانی شد'); invalidate(); },
    onError: (e) => fail(e, 'به‌روزرسانی منبع ناموفق بود'),
  });

  const remove = useMutation({
    mutationFn: (uuid: string) => api.delete<ApiResponse<null>>(`/api/v1/resource/${uuid}`),
    onSuccess: () => { toast.success('منبع حذف شد'); invalidate(); },
    onError: (e) => fail(e, 'حذف منبع ناموفق بود'),
  });

  /** جایگزینی کامل: مهارتی که در بدنه نیست، برداشته می‌شود. */
  const setSkills = useMutation({
    mutationFn: ({ uuid, skills }: { uuid: string; skills: { skill_uuid: string; level: number }[] }) =>
      api.put<ApiResponse<ClinicResource>>(`/api/v1/resource/${uuid}/skills`, { skills }),
    onSuccess: () => { toast.success('مهارت‌ها ذخیره شد'); invalidate(); },
    onError: (e) => fail(e, 'ذخیرهٔ مهارت‌ها ناموفق بود'),
  });

  return {
    resources: query.data?.data ?? [],
    loading: query.isLoading,
    create, update, remove, setSkills,
  };
}

export function useResourceTypes() {
  const qc = useQueryClient();
  const invalidate = () => qc.invalidateQueries({ queryKey: TYPES_KEY });

  const query = useQuery({
    queryKey: TYPES_KEY,
    queryFn: () => api.get<ApiResponse<ResourceType[]>>('/api/v1/resource-types'),
  });

  const create = useMutation({
    mutationFn: (d: { code: string; name: string }) =>
      api.post<ApiResponse<ResourceType>>('/api/v1/resource-types', d),
    onSuccess: () => { toast.success('نوع منبع افزوده شد'); invalidate(); },
    onError: (e) => fail(e, 'افزودن نوع منبع ناموفق بود'),
  });

  const update = useMutation({
    mutationFn: ({ uuid, d }: { uuid: string; d: { name?: string; active?: boolean } }) =>
      api.patch<ApiResponse<ResourceType>>(`/api/v1/resource-type/${uuid}`, d),
    onSuccess: () => { toast.success('نوع منبع به‌روزرسانی شد'); invalidate(); },
    onError: (e) => fail(e, 'به‌روزرسانی ناموفق بود'),
  });

  const remove = useMutation({
    mutationFn: (uuid: string) => api.delete<ApiResponse<null>>(`/api/v1/resource-type/${uuid}`),
    onSuccess: () => { toast.success('نوع منبع حذف شد'); invalidate(); },
    onError: (e) => fail(e, 'حذف نوع منبع ناموفق بود'),
  });

  return { types: query.data?.data ?? [], loading: query.isLoading, create, update, remove };
}

export function useSkills() {
  const qc = useQueryClient();
  const invalidate = () => qc.invalidateQueries({ queryKey: SKILLS_KEY });

  const query = useQuery({
    queryKey: SKILLS_KEY,
    queryFn: () => api.get<ApiResponse<Skill[]>>('/api/v1/skills'),
  });

  const create = useMutation({
    mutationFn: (d: { name: string }) => api.post<ApiResponse<Skill>>('/api/v1/skills', d),
    onSuccess: () => { toast.success('مهارت افزوده شد'); invalidate(); },
    onError: (e) => fail(e, 'افزودن مهارت ناموفق بود'),
  });

  const update = useMutation({
    mutationFn: ({ uuid, d }: { uuid: string; d: { name?: string; active?: boolean } }) =>
      api.patch<ApiResponse<Skill>>(`/api/v1/skill/${uuid}`, d),
    onSuccess: () => { toast.success('مهارت به‌روزرسانی شد'); invalidate(); },
    onError: (e) => fail(e, 'به‌روزرسانی ناموفق بود'),
  });

  const remove = useMutation({
    mutationFn: (uuid: string) => api.delete<ApiResponse<null>>(`/api/v1/skill/${uuid}`),
    onSuccess: () => { toast.success('مهارت حذف شد'); invalidate(); },
    // پیام سرور دقیق است («به N منبع داده شده»)، پس همان نشان داده می‌شود.
    onError: (e) => fail(e, 'حذف مهارت ناموفق بود'),
  });

  return { skills: query.data?.data ?? [], loading: query.isLoading, create, update, remove };
}

export function useResourcePools() {
  const qc = useQueryClient();
  const invalidate = () => qc.invalidateQueries({ queryKey: POOLS_KEY });

  const query = useQuery({
    queryKey: POOLS_KEY,
    queryFn: () => api.get<ApiResponse<ResourcePool[]>>('/api/v1/resource-pools'),
  });

  const create = useMutation({
    mutationFn: (d: { address_uuid: string; type_uuid: string; name: string }) =>
      api.post<ApiResponse<ResourcePool>>('/api/v1/resource-pools', d),
    onSuccess: () => { toast.success('استخر افزوده شد'); invalidate(); },
    onError: (e) => fail(e, 'افزودن استخر ناموفق بود'),
  });

  const update = useMutation({
    mutationFn: ({ uuid, d }: { uuid: string; d: { name?: string; active?: boolean } }) =>
      api.patch<ApiResponse<ResourcePool>>(`/api/v1/resource-pool/${uuid}`, d),
    onSuccess: () => { toast.success('استخر به‌روزرسانی شد'); invalidate(); },
    onError: (e) => fail(e, 'به‌روزرسانی ناموفق بود'),
  });

  const remove = useMutation({
    mutationFn: (uuid: string) => api.delete<ApiResponse<null>>(`/api/v1/resource-pool/${uuid}`),
    onSuccess: () => { toast.success('استخر حذف شد'); invalidate(); },
    onError: (e) => fail(e, 'حذف استخر ناموفق بود'),
  });

  /** جایگزینی کامل اعضا؛ سرور هم‌شعبه و هم‌نوع بودن را اجبار می‌کند. */
  const setMembers = useMutation({
    mutationFn: ({ uuid, members }: { uuid: string; members: { resource_uuid: string; priority: number }[] }) =>
      api.put<ApiResponse<ResourcePool>>(`/api/v1/resource-pool/${uuid}/members`, { members }),
    onSuccess: () => { toast.success('اعضای استخر ذخیره شد'); invalidate(); },
    onError: (e) => fail(e, 'ذخیرهٔ اعضا ناموفق بود'),
  });

  return { pools: query.data?.data ?? [], loading: query.isLoading, create, update, remove, setMembers };
}

/**
 * جزئیات یک منبع — تنها جایی که شمار نوبت‌های آیندهٔ آن می‌آید.
 *
 * در فهرست نمی‌آید چون آنجا یک کوئری per ردیف می‌شد؛ اینجا فقط وقتی لازم است که
 * کاربر دارد همان یک منبع را ویرایش می‌کند.
 */
export function useResourceDetail(uuid: string | undefined) {
  const query = useQuery({
    queryKey: ['resource-detail', uuid],
    queryFn: () =>
      api.get<ApiResponse<ClinicResource & { upcoming_appointments: number }>>(
        `/api/v1/resource/${uuid}`,
      ),
    enabled: !!uuid,
  });

  return {
    resource: query.data?.data,
    upcomingAppointments: query.data?.data?.upcoming_appointments ?? 0,
    loading: query.isLoading,
  };
}
