import { api } from '@common/services/api';
import type {
  OilSpillReportData,
  ReportType,
  Jurisdiction,
  ReportStatus,
  AnalysisCategory,
} from '../components/OilSpillReportTemplate';

// ============================================================
// API 응답 타입
// ============================================================

export interface ApiTemplateSection {
  sectCd: string;
  sectNm: string;
  fieldDef: { key: string; label: string; type: string; options?: string[] }[];
  sortOrd: number;
}

export interface ApiTemplate {
  tmplSn: number;
  tmplCd: string;
  tmplNm: string;
  icon: string;
  tmplDc: string;
  sections: ApiTemplateSection[];
}

export interface ApiCategoryTemplate {
  icon: string;
  label: string;
}

export interface ApiCategorySection {
  sectCd: string;
  sectNm: string;
  icon: string;
  sectDc: string;
  dfltYn: string;
  sortOrd: number;
}

export interface ApiCategory {
  ctgrSn: number;
  ctgrCd: string;
  ctgrNm: string;
  icon: string;
  ctgrDc: string;
  colorCd: string;
  borderColor: string;
  bgActive: string;
  reportNm: string;
  templates: ApiCategoryTemplate[];
  sections: ApiCategorySection[];
}

export interface ApiReportListItem {
  reportSn: number;
  tmplCd: string | null;
  tmplNm: string | null;
  ctgrCd: string | null;
  ctgrNm: string | null;
  title: string;
  jrsdCd: string | null;
  sttsCd: string;
  authorId: string;
  authorName: string;
  acdntSn?: number | null;
  regDtm: string;
  mdfcnDtm: string | null;
  hasMapCapture?: boolean;
}

export interface ApiReportSectionData {
  sectCd: string;
  includeYn: string;
  sectData: unknown;
  sortOrd: number;
}

export interface ApiReportDetail extends ApiReportListItem {
  acdntSn: number | null;
  sections: ApiReportSectionData[];
  step3MapImg?: string | null;
  step6MapImg?: string | null;
}

export interface ApiReportListResponse {
  items: ApiReportListItem[];
  totalCount: number;
  page: number;
  size: number;
}

// ============================================================
// 코드 매핑
// ============================================================

const STATUS_TO_CODE: Record<ReportStatus, string> = {
  완료: 'COMPLETED',
  수행중: 'IN_PROGRESS',
  테스트: 'DRAFT',
};

const CODE_TO_STATUS: Record<string, ReportStatus> = {
  COMPLETED: '완료',
  IN_PROGRESS: '수행중',
  DRAFT: '테스트',
};

const TMPL_CODE_TO_TYPE: Record<string, ReportType> = {
  INITIAL: '초기보고서',
  COMMAND: '지휘부 보고',
  FORECAST: '예측보고서',
  COMPREHENSIVE: '종합보고서',
  SPILL: '유출유 보고',
};

const TYPE_TO_TMPL_CODE: Record<ReportType, string> = {
  초기보고서: 'INITIAL',
  '지휘부 보고': 'COMMAND',
  예측보고서: 'FORECAST',
  종합보고서: 'COMPREHENSIVE',
  '유출유 보고': 'SPILL',
};

const CTGR_CODE_TO_CAT: Record<string, AnalysisCategory> = {
  OIL: '유출유 확산예측',
  HNS: 'HNS 대기확산',
  RESCUE: '긴급구난',
};

const CAT_TO_CTGR_CODE: Record<string, string> = {
  '유출유 확산예측': 'OIL',
  'HNS 대기확산': 'HNS',
  긴급구난: 'RESCUE',
};

// ============================================================
// 캐시 (템플릿/카테고리 — 변경 빈도 낮음)
// ============================================================

let templatesCache: ApiTemplate[] | null = null;
let categoriesCache: ApiCategory[] | null = null;

// ============================================================
// API 함수
// ============================================================

export async function fetchTemplates(): Promise<ApiTemplate[]> {
  if (templatesCache) return templatesCache;
  const res = await api.get<ApiTemplate[]>('/reports/templates');
  templatesCache = res.data;
  return res.data;
}

export async function fetchCategories(): Promise<ApiCategory[]> {
  if (categoriesCache) return categoriesCache;
  const res = await api.get<ApiCategory[]>('/reports/categories');
  categoriesCache = res.data;
  return res.data;
}

export async function fetchReports(params?: {
  jrsdCd?: string;
  tmplCd?: string;
  sttsCd?: string;
  search?: string;
  page?: number;
  size?: number;
}): Promise<ApiReportListResponse> {
  const res = await api.get<ApiReportListResponse>('/reports', { params });
  return res.data;
}

export async function fetchReport(sn: number): Promise<ApiReportDetail> {
  const res = await api.get<ApiReportDetail>(`/reports/${sn}`);
  return res.data;
}

export async function createReportApi(input: {
  tmplSn?: number;
  ctgrSn?: number;
  acdntSn?: number;
  title: string;
  jrsdCd?: string;
  sttsCd?: string;
  step3MapImg?: string;
  step6MapImg?: string;
  sections?: { sectCd: string; includeYn?: string; sectData: unknown; sortOrd?: number }[];
}): Promise<{ sn: number }> {
  const res = await api.post<{ sn: number }>('/reports', input);
  return res.data;
}

export async function updateReportApi(
  sn: number,
  input: {
    title?: string;
    jrsdCd?: string;
    sttsCd?: string;
    acdntSn?: number | null;
    step3MapImg?: string | null;
    step6MapImg?: string | null;
    sections?: { sectCd: string; includeYn?: string; sectData: unknown; sortOrd?: number }[];
  },
): Promise<void> {
  await api.post(`/reports/${sn}/update`, input);
}

export async function deleteReportApi(sn: number): Promise<void> {
  await api.post(`/reports/${sn}/delete`);
}

// ============================================================
// OilSpillReportData ↔ API 변환
// ============================================================

const SECTION_KEYS = [
  'incident',
  'tide',
  'weather',
  'spread',
  'aquaculture',
  'beaches',
  'markets',
  'esi',
  'species',
  'habitat',
  'sensitivity',
  'vessels',
  'recovery',
  'result',
] as const;

async function findTmplSn(reportType: ReportType): Promise<number | undefined> {
  const tmpls = await fetchTemplates();
  const code = TYPE_TO_TMPL_CODE[reportType];
  return tmpls.find((t) => t.tmplCd === code)?.tmplSn;
}

async function findCtgrSn(category: AnalysisCategory): Promise<number | undefined> {
  if (!category) return undefined;
  const cats = await fetchCategories();
  const code = CAT_TO_CTGR_CODE[category];
  return cats.find((c) => c.ctgrCd === code)?.ctgrSn;
}

export async function saveReport(data: OilSpillReportData): Promise<number> {
  const tmplSn = await findTmplSn(data.reportType);
  const ctgrSn = data.analysisCategory ? await findCtgrSn(data.analysisCategory) : undefined;
  const sttsCd = STATUS_TO_CODE[data.status] || 'DRAFT';

  const sections: { sectCd: string; sectData: unknown; sortOrd: number }[] = [];
  let sortOrd = 0;
  for (const key of SECTION_KEYS) {
    sections.push({ sectCd: key, sectData: data[key], sortOrd: sortOrd++ });
  }
  // analysis + etcEquipment 합산
  sections.push({
    sectCd: 'analysis',
    sectData: { analysis: data.analysis, etcEquipment: data.etcEquipment },
    sortOrd: sortOrd++,
  });

  // 민감자원 지도 이미지 (섹션으로 저장)
  const extData = data as OilSpillReportData & { reportSn?: number; acdntSn?: number };
  if (extData.sensitiveMapImage !== undefined) {
    sections.push({
      sectCd: 'sensitive-map',
      sectData: { mapImage: extData.sensitiveMapImage },
      sortOrd: sortOrd++,
    });
  }
  // 통합민감도 평가 지도 이미지 (섹션으로 저장)
  if (extData.sensitivityMapImage !== undefined) {
    sections.push({
      sectCd: 'sensitivity-map',
      sectData: { mapImage: extData.sensitivityMapImage },
      sortOrd: sortOrd++,
    });
  }

  // reportSn이 있으면 update, 없으면 create
  const existingSn = extData.reportSn;
  if (existingSn) {
    await updateReportApi(existingSn, {
      title: data.title || data.incident.name || '보고서',
      jrsdCd: data.jurisdiction,
      sttsCd,
      acdntSn: extData.acdntSn ?? null,
      step3MapImg: data.step3MapImage !== undefined ? data.step3MapImage || null : undefined,
      step6MapImg: data.step6MapImage !== undefined ? data.step6MapImage || null : undefined,
      sections,
    });
    return existingSn;
  }

  const result = await createReportApi({
    tmplSn,
    ctgrSn,
    acdntSn: extData.acdntSn,
    title: data.title || data.incident.name || '보고서',
    jrsdCd: data.jurisdiction,
    sttsCd,
    step3MapImg: data.step3MapImage || undefined,
    step6MapImg: data.step6MapImage || undefined,
    sections,
  });
  return result.sn;
}

export function apiListItemToReportData(item: ApiReportListItem): OilSpillReportData {
  return {
    id: String(item.reportSn),
    title: item.title,
    createdAt: item.regDtm,
    updatedAt: item.mdfcnDtm || item.regDtm,
    author: item.authorName || '',
    reportType: (item.tmplCd ? TMPL_CODE_TO_TYPE[item.tmplCd] : '초기보고서') || '초기보고서',
    analysisCategory: (item.ctgrCd ? CTGR_CODE_TO_CAT[item.ctgrCd] : '') || '',
    jurisdiction: (item.jrsdCd as Jurisdiction) || '',
    status: CODE_TO_STATUS[item.sttsCd] || '테스트',
    hasMapCapture: item.hasMapCapture,
    acdntSn: item.acdntSn ?? undefined,
    // 목록에서는 섹션 데이터 없음 — 빈 기본값
    incident: {
      name: '',
      writeTime: '',
      shipName: '',
      agent: '',
      location: '',
      lat: '',
      lon: '',
      occurTime: '',
      accidentType: '',
      pollutant: '',
      spillAmount: '',
      depth: '',
      seabed: '',
    },
    tide: [],
    weather: [],
    spread: [],
    analysis: '',
    aquaculture: [],
    beaches: [],
    markets: [],
    esi: [],
    species: [],
    habitat: [],
    sensitivity: [],
    vessels: [],
    etcEquipment: '',
    recovery: [],
    result: {
      spillTotal: '',
      weatheredTotal: '',
      recoveredTotal: '',
      seaRemainTotal: '',
      coastAttachTotal: '',
    },
  };
}

export function apiDetailToReportData(
  detail: ApiReportDetail,
): OilSpillReportData & { reportSn: number } {
  const base = apiListItemToReportData(detail);
  const reportData = { ...base, reportSn: detail.reportSn } as OilSpillReportData & {
    reportSn: number;
  };

  // 섹션 데이터 복원
  for (const sect of detail.sections) {
    const d = sect.sectData as Record<string, unknown>;
    if (!d) continue;

    switch (sect.sectCd) {
      case 'incident':
        reportData.incident = d as OilSpillReportData['incident'];
        break;
      case 'tide':
        reportData.tide = d as OilSpillReportData['tide'];
        break;
      case 'weather':
        reportData.weather = d as OilSpillReportData['weather'];
        break;
      case 'spread':
        reportData.spread = d as OilSpillReportData['spread'];
        break;
      case 'analysis':
        if (typeof d === 'object' && d !== null) {
          reportData.analysis = (d as { analysis?: string }).analysis || '';
          reportData.etcEquipment = (d as { etcEquipment?: string }).etcEquipment || '';
        }
        break;
      case 'aquaculture':
        reportData.aquaculture = d as OilSpillReportData['aquaculture'];
        break;
      case 'beaches':
        reportData.beaches = d as OilSpillReportData['beaches'];
        break;
      case 'markets':
        reportData.markets = d as OilSpillReportData['markets'];
        break;
      case 'esi':
        reportData.esi = d as OilSpillReportData['esi'];
        break;
      case 'species':
        reportData.species = d as OilSpillReportData['species'];
        break;
      case 'habitat':
        reportData.habitat = d as OilSpillReportData['habitat'];
        break;
      case 'sensitivity':
        reportData.sensitivity = d as OilSpillReportData['sensitivity'];
        break;
      case 'vessels':
        reportData.vessels = d as OilSpillReportData['vessels'];
        break;
      case 'recovery':
        reportData.recovery = d as OilSpillReportData['recovery'];
        break;
      case 'result':
        reportData.result = d as OilSpillReportData['result'];
        break;
      case 'sensitive-map':
        reportData.sensitiveMapImage = (d as { mapImage?: string }).mapImage;
        break;
      case 'sensitivity-map':
        reportData.sensitivityMapImage = (d as { mapImage?: string }).mapImage;
        break;
    }
  }

  // location이 비어있고 좌표가 있으면 좌표 문자열로 대체 (기존 보고서 대응)
  if (!reportData.incident.location && reportData.incident.lat && reportData.incident.lon) {
    reportData.incident.location = `위도 ${parseFloat(reportData.incident.lat).toFixed(4)}, 경도 ${parseFloat(reportData.incident.lon).toFixed(4)}`;
  }

  if (detail.step3MapImg) {
    reportData.step3MapImage = detail.step3MapImg;
  }
  if (detail.step6MapImg) {
    reportData.step6MapImage = detail.step6MapImg;
  }
  if (detail.acdntSn != null) {
    (reportData as typeof reportData & { acdntSn?: number }).acdntSn = detail.acdntSn;
  }

  return reportData;
}

export async function loadReportsFromApi(): Promise<OilSpillReportData[]> {
  const res = await fetchReports({ size: 100 });
  return res.items.map(apiListItemToReportData);
}

export async function loadReportDetail(
  sn: number,
): Promise<OilSpillReportData & { reportSn: number }> {
  const detail = await fetchReport(sn);
  return apiDetailToReportData(detail);
}
