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

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

interface ZoneItem {
  cstSrvyZoneSn: number;
  zoneCd: string;
  zoneNm: string;
  jrsdNm: string;
  sectCnt: number;
  latCenter: number;
  lngCenter: number;
  latRange: number;
  lngRange: number;
}

interface SectionListItem {
  cstSectSn: number;
  sectCd: string;
  sectNm: string;
  cstTpCd: string;
  esiCd: string;
  esiNum: number;
  lenM: number;
  snstvtCd: string;
  srvySttsCd: string;
  lat: number;
  lng: number;
  tags: string[];
  zoneCd: string;
  zoneNm: string;
  jrsdNm: string;
}

interface SectionDetail {
  cstSectSn: number;
  sectCd: string;
  sectNm: string;
  cstTpCd: string;
  esiCd: string;
  esiNum: number;
  lenM: number;
  snstvtCd: string;
  srvySttsCd: string;
  lat: number;
  lng: number;
  tags: string[];
  geomJson: Record<string, unknown> | null;
  zoneCd: string;
  zoneNm: string;
  jrsdNm: string;
  shoreTp: string | null;
  accessDc: string | null;
  accessPt: string | null;
  sensitiveInfo: { t: string; v: string }[];
  cleanupMethods: string[];
  endCriteria: string[];
  notes: string[];
}

// ============================================================
// 관할청 목록 조회
// ============================================================

export async function listOffices(): Promise<string[]> {
  const sql = `
    SELECT DISTINCT OFFICE_CD
    FROM wing.CST_SRVY_ZONE
    WHERE USE_YN = 'Y' AND OFFICE_CD IS NOT NULL
    ORDER BY OFFICE_CD
  `;
  const { rows } = await wingPool.query(sql);
  return rows.map((r: Record<string, unknown>) => r.office_cd as string);
}

// ============================================================
// 관할서 목록 조회
// ============================================================

export async function listJurisdictions(officeCd?: string): Promise<string[]> {
  const conditions: string[] = ["USE_YN = 'Y'", 'JRSD_NM IS NOT NULL'];
  const params: unknown[] = [];
  let idx = 1;
  if (officeCd) {
    conditions.push(`OFFICE_CD = $${idx++}`);
    params.push(officeCd);
  }
  const sql = `
    SELECT DISTINCT JRSD_NM
    FROM wing.CST_SRVY_ZONE
    WHERE ${conditions.join(' AND ')}
    ORDER BY JRSD_NM
  `;
  const { rows } = await wingPool.query(sql, params);
  return rows.map((r: Record<string, unknown>) => r.jrsd_nm as string);
}

// ============================================================
// 조사구역 목록 조회
// ============================================================

export async function listZones(filters?: {
  jurisdiction?: string;
  officeCd?: string;
}): Promise<ZoneItem[]> {
  const conditions: string[] = ["USE_YN = 'Y'"];
  const params: unknown[] = [];
  let idx = 1;

  if (filters?.jurisdiction) {
    conditions.push(`JRSD_NM ILIKE '%' || $${idx++} || '%'`);
    params.push(filters.jurisdiction);
  }
  if (filters?.officeCd) {
    conditions.push(`OFFICE_CD = $${idx++}`);
    params.push(filters.officeCd);
  }

  const where = 'WHERE ' + conditions.join(' AND ');

  const sql = `
    SELECT CST_SRVY_ZONE_SN, ZONE_CD, ZONE_NM, JRSD_NM,
           SECT_CNT, LAT_CENTER, LNG_CENTER, LAT_RANGE, LNG_RANGE
    FROM wing.CST_SRVY_ZONE
    ${where}
    ORDER BY CST_SRVY_ZONE_SN
  `;

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

  return rows.map((r: Record<string, unknown>) => ({
    cstSrvyZoneSn: r.cst_srvy_zone_sn as number,
    zoneCd: r.zone_cd as string,
    zoneNm: r.zone_nm as string,
    jrsdNm: r.jrsd_nm as string,
    sectCnt: r.sect_cnt as number,
    latCenter: parseFloat(r.lat_center as string),
    lngCenter: parseFloat(r.lng_center as string),
    latRange: parseFloat(r.lat_range as string),
    lngRange: parseFloat(r.lng_range as string),
  }));
}

// ============================================================
// 해안구간 목록 조회 (필터링)
// ============================================================

export async function listSections(filters: {
  zone?: string;
  status?: string;
  sensitivity?: string;
  jurisdiction?: string;
  search?: string;
  officeCd?: string;
}): Promise<SectionListItem[]> {
  const conditions: string[] = [];
  const params: unknown[] = [];
  let idx = 1;

  if (filters.zone) {
    conditions.push(`z.ZONE_CD = $${idx++}`);
    params.push(filters.zone);
  }
  if (filters.status) {
    conditions.push(`s.SRVY_STTS_CD = $${idx++}`);
    params.push(filters.status);
  }
  if (filters.sensitivity) {
    conditions.push(`s.SNSTVT_CD = $${idx++}`);
    params.push(filters.sensitivity);
  }
  if (filters.jurisdiction) {
    conditions.push(`z.JRSD_NM ILIKE '%' || $${idx++} || '%'`);
    params.push(filters.jurisdiction);
  }
  if (filters.search) {
    conditions.push(`s.SECT_NM ILIKE '%' || $${idx++} || '%'`);
    params.push(filters.search);
  }
  if (filters.officeCd) {
    conditions.push(`z.OFFICE_CD = $${idx++}`);
    params.push(filters.officeCd);
  }

  conditions.push("s.USE_YN = 'Y'");
  conditions.push("z.USE_YN = 'Y'");
  const where = 'WHERE ' + conditions.join(' AND ');

  const sql = `
    SELECT s.CST_SECT_SN, s.SECT_CD, s.SECT_NM, s.CST_TP_CD,
           s.ESI_CD, s.ESI_NUM, s.LEN_M, s.SNSTVT_CD, s.SRVY_STTS_CD,
           s.LAT, s.LNG, s.TAGS,
           z.ZONE_CD, z.ZONE_NM, z.JRSD_NM
    FROM wing.CST_SECT s
    JOIN wing.CST_SRVY_ZONE z ON z.CST_SRVY_ZONE_SN = s.CST_SRVY_ZONE_SN
    ${where}
    ORDER BY s.CST_SECT_SN
  `;

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

  return rows.map((r: Record<string, unknown>) => ({
    cstSectSn: r.cst_sect_sn as number,
    sectCd: r.sect_cd as string,
    sectNm: r.sect_nm as string,
    cstTpCd: r.cst_tp_cd as string,
    esiCd: r.esi_cd as string,
    esiNum: r.esi_num as number,
    lenM: r.len_m as number,
    snstvtCd: r.snstvt_cd as string,
    srvySttsCd: r.srvy_stts_cd as string,
    lat: parseFloat(r.lat as string),
    lng: parseFloat(r.lng as string),
    tags: (r.tags as string[]) ?? [],
    zoneCd: r.zone_cd as string,
    zoneNm: r.zone_nm as string,
    jrsdNm: r.jrsd_nm as string,
  }));
}

// ============================================================
// 해안구간 단건 상세 조회 (JSONB 포함)
// ============================================================

export async function getSection(sn: number): Promise<SectionDetail | null> {
  const sql = `
    SELECT s.CST_SECT_SN, s.SECT_CD, s.SECT_NM, s.CST_TP_CD,
           s.ESI_CD, s.ESI_NUM, s.LEN_M, s.SNSTVT_CD, s.SRVY_STTS_CD,
           s.LAT, s.LNG, s.TAGS,
           ST_AsGeoJSON(s.GEOM)::jsonb AS geom_json,
           s.SHORE_TP, s.ACCESS_DC, s.ACCESS_PT,
           s.SENSITIVE_INFO, s.CLEANUP_METHODS, s.END_CRITERIA, s.NOTES,
           z.ZONE_CD, z.ZONE_NM, z.JRSD_NM
    FROM wing.CST_SECT s
    JOIN wing.CST_SRVY_ZONE z ON z.CST_SRVY_ZONE_SN = s.CST_SRVY_ZONE_SN
    WHERE s.CST_SECT_SN = $1 AND s.USE_YN = 'Y'
  `;

  const { rows } = await wingPool.query(sql, [sn]);
  if (rows.length === 0) return null;

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

  return {
    cstSectSn: r.cst_sect_sn as number,
    sectCd: r.sect_cd as string,
    sectNm: r.sect_nm as string,
    cstTpCd: r.cst_tp_cd as string,
    esiCd: r.esi_cd as string,
    esiNum: r.esi_num as number,
    lenM: r.len_m as number,
    snstvtCd: r.snstvt_cd as string,
    srvySttsCd: r.srvy_stts_cd as string,
    lat: parseFloat(r.lat as string),
    lng: parseFloat(r.lng as string),
    tags: (r.tags as string[]) ?? [],
    geomJson: (r.geom_json as Record<string, unknown>) ?? null,
    zoneCd: r.zone_cd as string,
    zoneNm: r.zone_nm as string,
    jrsdNm: r.jrsd_nm as string,
    shoreTp: (r.shore_tp as string) ?? null,
    accessDc: (r.access_dc as string) ?? null,
    accessPt: (r.access_pt as string) ?? null,
    sensitiveInfo: (r.sensitive_info as { t: string; v: string }[]) ?? [],
    cleanupMethods: (r.cleanup_methods as string[]) ?? [],
    endCriteria: (r.end_criteria as string[]) ?? [],
    notes: (r.notes as string[]) ?? [],
  };
}
