import { useRequestFetch } from '#imports';
import type {
  ComponentModelStructure,
  PieceModelStructure,
  ProductModelStructure,
} from '~/shared/types/inventory';

export type ModelCategory = 'COMPONENT' | 'PIECE' | 'PRODUCT';

export type ModelTypeStructure =
  | ComponentModelStructure
  | PieceModelStructure
  | ProductModelStructure
  | null;

export interface BaseModelTypePayload {
  name: string;
  code: string;
  notes?: string | null;
  description?: string | null;
}

export interface ComponentModelTypePayload extends BaseModelTypePayload {
  category: 'COMPONENT';
  structure?: ComponentModelStructure | null;
  referenceFormula?: string | null;
  requiredFieldsForReference?: string[] | null;
}

export interface PieceModelTypePayload extends BaseModelTypePayload {
  category: 'PIECE';
  structure?: PieceModelStructure | null;
  referenceFormula?: string | null;
  requiredFieldsForReference?: string[] | null;
}

export interface ProductModelTypePayload extends BaseModelTypePayload {
  category: 'PRODUCT';
  structure?: ProductModelStructure | null;
}

export type ModelTypePayload =
  | ComponentModelTypePayload
  | PieceModelTypePayload
  | ProductModelTypePayload;

export interface ModelType extends BaseModelTypePayload {
  id: string;
  createdAt: string;
  updatedAt: string;
  category: ModelCategory;
  structure: ModelTypeStructure;
  referenceFormula?: string | null;
  requiredFieldsForReference?: string[] | null;
}

export interface ModelTypeListParams {
  q?: string;
  category?: ModelCategory;
  sort?: 'name' | 'createdAt';
  dir?: 'asc' | 'desc';
  limit?: number;
  offset?: number;
}

export interface ModelTypeListResponse {
  items: ModelType[];
  total: number;
  offset: number;
  limit: number;
}

const ENDPOINT = '/model_types';

function resolveBaseUrl() {
  const runtimeConfig = useRuntimeConfig();
  return runtimeConfig.public.apiBaseUrl || '';
}

function createOptions(options: Record<string, unknown> = {}): Record<string, unknown> {
  return {
    baseURL: resolveBaseUrl(),
    credentials: 'include',
    ...options,
  };
}

const normalizeModelType = (item: any): ModelType => {
  if (!item || typeof item !== 'object') {
    return item as ModelType;
  }
  return item as ModelType;
};

export async function listModelTypes(params: ModelTypeListParams = {}, opts: { signal?: AbortSignal } = {}) {
  const requestFetch = useRequestFetch();
  const query: Record<string, string | number> = {};

  if (params.q) {
    query.name = params.q;
  }
  if (params.category) {
    query.category = params.category;
  }

  // Sort: API Platform OrderFilter uses order[field]=direction
  const sortField = params.sort || 'name';
  const sortDir = params.dir || 'asc';
  query[`order[${sortField}]`] = sortDir;

  // Pagination: API Platform uses page + itemsPerPage
  const effectiveLimit = typeof params.limit === 'number' ? params.limit : 20;
  const effectiveOffset = typeof params.offset === 'number' ? params.offset : 0;
  const page = Math.floor(effectiveOffset / effectiveLimit) + 1;

  query.itemsPerPage = effectiveLimit;
  query.page = page;

  const payload = await requestFetch<Record<string, any>>(ENDPOINT, createOptions({
    method: 'GET',
    query,
    signal: opts.signal,
  }));

  const rawItems = Array.isArray(payload?.member)
    ? payload.member
    : Array.isArray(payload?.['hydra:member'])
      ? payload['hydra:member']
      : Array.isArray(payload?.items)
        ? payload.items
        : [];

  const total = typeof payload?.totalItems === 'number'
    ? payload.totalItems
    : typeof payload?.['hydra:totalItems'] === 'number'
      ? payload['hydra:totalItems']
      : rawItems.length;

  const items = rawItems.map(normalizeModelType);

  return {
    items,
    total,
    offset: effectiveOffset,
    limit: effectiveLimit,
  } satisfies ModelTypeListResponse;
}

export function createModelType(payload: ModelTypePayload, opts: { signal?: AbortSignal } = {}) {
  const requestFetch = useRequestFetch();
  return requestFetch<ModelType>(ENDPOINT, createOptions({
    method: 'POST',
    headers: {
      'Content-Type': 'application/ld+json',
      Accept: 'application/ld+json',
    },
    body: payload,
    signal: opts.signal,
  })).then(normalizeModelType);
}

export function updateModelType(id: string, payload: Partial<ModelTypePayload>, opts: { signal?: AbortSignal } = {}) {
  const requestFetch = useRequestFetch();
  return requestFetch<ModelType>(`${ENDPOINT}/${id}`, createOptions({
    method: 'PATCH',
    headers: {
      'Content-Type': 'application/merge-patch+json',
      Accept: 'application/ld+json',
    },
    body: payload,
    signal: opts.signal,
  })).then(normalizeModelType);
}

export function deleteModelType(id: string, opts: { signal?: AbortSignal } = {}) {
  const requestFetch = useRequestFetch();
  return requestFetch<void>(`${ENDPOINT}/${id}`, createOptions({
    method: 'DELETE',
    signal: opts.signal,
  }));
}

export function getModelType(id: string, opts: { signal?: AbortSignal } = {}) {
  const requestFetch = useRequestFetch();
  return requestFetch<ModelType>(`${ENDPOINT}/${id}`, createOptions({
    method: 'GET',
    signal: opts.signal,
  })).then(normalizeModelType);
}

export interface ConversionCheck {
  canConvert: boolean;
  direction: 'piece_to_component' | 'component_to_piece' | null;
  itemCount: number;
  names: string[];
  blockers: string[];
}

export interface ConversionResult {
  success: boolean;
  convertedCount: number;
  error?: string | null;
}

export function checkConversion(id: string, opts: { signal?: AbortSignal } = {}) {
  const requestFetch = useRequestFetch();
  return requestFetch<ConversionCheck>(`${ENDPOINT}/${id}/conversion-check`, createOptions({
    method: 'GET',
    signal: opts.signal,
  }));
}

export function convertCategory(id: string, opts: { signal?: AbortSignal } = {}) {
  const requestFetch = useRequestFetch();
  return requestFetch<ConversionResult>(`${ENDPOINT}/${id}/convert`, createOptions({
    method: 'POST',
    signal: opts.signal,
  }));
}

export interface SyncPreviewResult {
  modelTypeId: string;
  category: string;
  itemCount: number;
  additions: Record<string, number>;
  deletions: Record<string, number>;
  modifications: Record<string, number>;
}

export interface SyncExecuteResult {
  itemsUpdated: number;
  additions: Record<string, number>;
  deletions: Record<string, number>;
  modifications: Record<string, number>;
}

export function syncPreview(id: string, structure: unknown, opts: { signal?: AbortSignal } = {}) {
  const requestFetch = useRequestFetch();
  return requestFetch<SyncPreviewResult>(`${ENDPOINT}/${id}/sync-preview`, createOptions({
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
    },
    body: { structure },
    signal: opts.signal,
  }));
}

export function syncExecute(id: string, confirmation: { confirmDeletions: boolean; confirmTypeChanges: boolean }, opts: { signal?: AbortSignal } = {}) {
  const requestFetch = useRequestFetch();
  return requestFetch<SyncExecuteResult>(`${ENDPOINT}/${id}/sync`, createOptions({
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
    },
    body: confirmation,
    signal: opts.signal,
  }));
}
