import { wingPool } from '../db/wingDb.js';

// ============================================================
// 인터페이스
// ============================================================

interface EquipItem {
  category: string;
  icon: string;
  count: number;
}

interface ContactItem {
  role: string;
  name: string;
  phone: string;
}

interface OrgListItem {
  orgSn: number;
  orgTp: string;
  jrsdNm: string;
  areaNm: string;
  orgNm: string;
  addr: string;
  tel: string;
  lat: number;
  lng: number;
  pinSize: string;
  vesselCnt: number;
  skimmerCnt: number;
  pumpCnt: number;
  vehicleCnt: number;
  sprayerCnt: number;
  totalAssets: number;
}

interface OrgDetail extends OrgListItem {
  equipment: EquipItem[];
  contacts: ContactItem[];
}

interface UploadLogItem {
  logSn: number;
  fileNm: string;
  uploaderNm: string;
  uploadCnt: number;
  regDtm: string;
}

// ============================================================
// 기관 목록 조회
// ============================================================
export async function listOrganizations(filters: {
  orgTp?: string;
  jrsd?: string;
  search?: string;
}): Promise<OrgListItem[]> {
  const conditions: string[] = ["USE_YN = 'Y'"];
  const params: unknown[] = [];
  let idx = 1;

  if (filters.orgTp) {
    conditions.push(`ORG_TP = $${idx++}`);
    params.push(filters.orgTp);
  }
  if (filters.jrsd) {
    conditions.push(`JRSD_NM LIKE '%' || $${idx++} || '%'`);
    params.push(filters.jrsd);
  }
  if (filters.search) {
    conditions.push(`(ORG_NM LIKE '%' || $${idx++} || '%' OR ADDR LIKE '%' || $${idx++} || '%')`);
    params.push(filters.search, filters.search);
  }

  const sql = `
    SELECT ORG_SN, ORG_TP, JRSD_NM, AREA_NM, ORG_NM, ADDR, TEL,
           LAT, LNG, PIN_SIZE,
           VESSEL_CNT, SKIMMER_CNT, PUMP_CNT, VEHICLE_CNT, SPRAYER_CNT, TOTAL_ASSETS
    FROM wing.ASSET_ORG
    WHERE ${conditions.join(' AND ')}
    ORDER BY JRSD_NM, ORG_TP, ORG_NM
  `;

  const { rows } = await wingPool.query(sql, params);

  return rows.map((r: Record<string, unknown>) => ({
    orgSn: r.org_sn as number,
    orgTp: r.org_tp as string,
    jrsdNm: r.jrsd_nm as string,
    areaNm: r.area_nm as string,
    orgNm: r.org_nm as string,
    addr: r.addr as string,
    tel: r.tel as string,
    lat: parseFloat(r.lat as string),
    lng: parseFloat(r.lng as string),
    pinSize: r.pin_size as string,
    vesselCnt: r.vessel_cnt as number,
    skimmerCnt: r.skimmer_cnt as number,
    pumpCnt: r.pump_cnt as number,
    vehicleCnt: r.vehicle_cnt as number,
    sprayerCnt: r.sprayer_cnt as number,
    totalAssets: r.total_assets as number,
  }));
}

// ============================================================
// 기관 상세 조회 (장비 + 담당자 포함)
// ============================================================
export async function getOrganization(orgSn: number): Promise<OrgDetail | null> {
  const orgSql = `
    SELECT ORG_SN, ORG_TP, JRSD_NM, AREA_NM, ORG_NM, ADDR, TEL,
           LAT, LNG, PIN_SIZE,
           VESSEL_CNT, SKIMMER_CNT, PUMP_CNT, VEHICLE_CNT, SPRAYER_CNT, TOTAL_ASSETS
    FROM wing.ASSET_ORG
    WHERE ORG_SN = $1 AND USE_YN = 'Y'
  `;
  const { rows: orgRows } = await wingPool.query(orgSql, [orgSn]);
  if (orgRows.length === 0) return null;

  const r = orgRows[0] as Record<string, unknown>;

  const equipSql = `
    SELECT CTGR_NM, ICON, QTY FROM wing.ASSET_EQUIP
    WHERE ORG_SN = $1 ORDER BY SORT_ORD, EQUIP_SN
  `;
  const { rows: equipRows } = await wingPool.query(equipSql, [orgSn]);

  const contactSql = `
    SELECT ROLE_NM, CONTACT_NM, TEL FROM wing.ASSET_CONTACT
    WHERE ORG_SN = $1 ORDER BY SORT_ORD, CONTACT_SN
  `;
  const { rows: contactRows } = await wingPool.query(contactSql, [orgSn]);

  return {
    orgSn: r.org_sn as number,
    orgTp: r.org_tp as string,
    jrsdNm: r.jrsd_nm as string,
    areaNm: r.area_nm as string,
    orgNm: r.org_nm as string,
    addr: r.addr as string,
    tel: r.tel as string,
    lat: parseFloat(r.lat as string),
    lng: parseFloat(r.lng as string),
    pinSize: r.pin_size as string,
    vesselCnt: r.vessel_cnt as number,
    skimmerCnt: r.skimmer_cnt as number,
    pumpCnt: r.pump_cnt as number,
    vehicleCnt: r.vehicle_cnt as number,
    sprayerCnt: r.sprayer_cnt as number,
    totalAssets: r.total_assets as number,
    equipment: equipRows.map((e: Record<string, unknown>) => ({
      category: e.ctgr_nm as string,
      icon: e.icon as string,
      count: e.qty as number,
    })),
    contacts: contactRows.map((c: Record<string, unknown>) => ({
      role: c.role_nm as string,
      name: c.contact_nm as string,
      phone: c.tel as string,
    })),
  };
}

// ============================================================
// 근처 기관 조회 (PostGIS ST_DWithin)
// ============================================================

export interface NearbyOrgItem extends OrgListItem {
  distanceNm: number;
}

export async function listNearbyOrganizations(
  lat: number,
  lng: number,
  radiusNm: number,
): Promise<NearbyOrgItem[]> {
  const radiusMeters = radiusNm * 1852;
  const sql = `
    SELECT ORG_SN, ORG_TP, JRSD_NM, AREA_NM, ORG_NM, ADDR, TEL,
           LAT, LNG, PIN_SIZE,
           VESSEL_CNT, SKIMMER_CNT, PUMP_CNT, VEHICLE_CNT, SPRAYER_CNT, TOTAL_ASSETS,
           ST_Distance(GEOM::geography, ST_SetSRID(ST_MakePoint($2, $1), 4326)::geography) / 1852.0 AS distance_nm
    FROM wing.ASSET_ORG
    WHERE USE_YN = 'Y'
      AND GEOM IS NOT NULL
      AND ST_DWithin(GEOM::geography, ST_SetSRID(ST_MakePoint($2, $1), 4326)::geography, $3)
    ORDER BY distance_nm
  `;
  const { rows } = await wingPool.query(sql, [lat, lng, radiusMeters]);

  return rows.map((r: Record<string, unknown>) => ({
    orgSn: r.org_sn as number,
    orgTp: r.org_tp as string,
    jrsdNm: r.jrsd_nm as string,
    areaNm: r.area_nm as string,
    orgNm: r.org_nm as string,
    addr: r.addr as string,
    tel: r.tel as string,
    lat: parseFloat(r.lat as string),
    lng: parseFloat(r.lng as string),
    pinSize: r.pin_size as string,
    vesselCnt: r.vessel_cnt as number,
    skimmerCnt: r.skimmer_cnt as number,
    pumpCnt: r.pump_cnt as number,
    vehicleCnt: r.vehicle_cnt as number,
    sprayerCnt: r.sprayer_cnt as number,
    totalAssets: r.total_assets as number,
    distanceNm: parseFloat(r.distance_nm as string),
  }));
}

// ============================================================
// 선박보험(유류오염보장계약) 조회
// ============================================================

interface InsuranceListItem {
  insSn: number;
  shipNo: string;
  shipNm: string;
  callSign: string;
  imoNo: string;
  shipTp: string;
  shipTpDetail: string;
  ownerNm: string;
  grossTon: string;
  insurerNm: string;
  liabilityYn: string;
  oilPollutionYn: string;
  fuelOilYn: string;
  wreckRemovalYn: string;
  validStart: string;
  validEnd: string;
  issueOrg: string;
}

export async function listInsurance(filters: {
  search?: string;
  shipTp?: string;
  issueOrg?: string;
  insurer?: string;
  page?: number;
  limit?: number;
}): Promise<{ rows: InsuranceListItem[]; total: number }> {
  const conditions: string[] = [];
  const params: unknown[] = [];
  let idx = 1;

  if (filters.search) {
    conditions.push(`(ship_nm LIKE '%' || $${idx} || '%' OR call_sign LIKE '%' || $${idx} || '%' OR imo_no LIKE '%' || $${idx} || '%' OR owner_nm LIKE '%' || $${idx} || '%')`);
    params.push(filters.search);
    idx++;
  }
  if (filters.shipTp) {
    conditions.push(`ship_tp = $${idx++}`);
    params.push(filters.shipTp);
  }
  if (filters.issueOrg) {
    conditions.push(`issue_org LIKE '%' || $${idx++} || '%'`);
    params.push(filters.issueOrg);
  }
  if (filters.insurer) {
    conditions.push(`insurer_nm LIKE '%' || $${idx++} || '%'`);
    params.push(filters.insurer);
  }

  const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
  const limit = Math.min(filters.limit || 50, 200);
  const offset = ((filters.page || 1) - 1) * limit;

  const countSql = `SELECT COUNT(*) AS cnt FROM wing.SHIP_INSURANCE ${where}`;
  const { rows: countRows } = await wingPool.query(countSql, params);
  const total = parseInt(countRows[0].cnt as string, 10);

  const sql = `
    SELECT ins_sn, ship_no, ship_nm, call_sign, imo_no, ship_tp, ship_tp_detail,
           owner_nm, gross_ton, insurer_nm,
           liability_yn, oil_pollution_yn, fuel_oil_yn, wreck_removal_yn,
           valid_start, valid_end, issue_org
    FROM wing.SHIP_INSURANCE
    ${where}
    ORDER BY valid_end DESC, ins_sn
    LIMIT $${idx++} OFFSET $${idx++}
  `;
  params.push(limit, offset);

  const { rows } = await wingPool.query(sql, params);

  return {
    total,
    rows: rows.map((r: Record<string, unknown>) => ({
      insSn: r.ins_sn as number,
      shipNo: r.ship_no as string,
      shipNm: r.ship_nm as string,
      callSign: r.call_sign as string,
      imoNo: r.imo_no as string,
      shipTp: r.ship_tp as string,
      shipTpDetail: r.ship_tp_detail as string,
      ownerNm: r.owner_nm as string,
      grossTon: r.gross_ton as string,
      insurerNm: r.insurer_nm as string,
      liabilityYn: r.liability_yn as string,
      oilPollutionYn: r.oil_pollution_yn as string,
      fuelOilYn: r.fuel_oil_yn as string,
      wreckRemovalYn: r.wreck_removal_yn as string,
      validStart: (r.valid_start as Date)?.toISOString().slice(0, 10) ?? '',
      validEnd: (r.valid_end as Date)?.toISOString().slice(0, 10) ?? '',
      issueOrg: r.issue_org as string,
    })),
  };
}

// ============================================================
// 업로드 이력 조회
// ============================================================
export async function listUploadLogs(limit = 20): Promise<UploadLogItem[]> {
  const sql = `
    SELECT LOG_SN, FILE_NM, UPLOADER_NM, UPLOAD_CNT, REG_DTM
    FROM wing.ASSET_UPLOAD_LOG
    ORDER BY REG_DTM DESC
    LIMIT $1
  `;
  const { rows } = await wingPool.query(sql, [limit]);

  return rows.map((r: Record<string, unknown>) => ({
    logSn: r.log_sn as number,
    fileNm: r.file_nm as string,
    uploaderNm: r.uploader_nm as string,
    uploadCnt: r.upload_cnt as number,
    regDtm: (r.reg_dtm as Date).toISOString(),
  }));
}
