import { z } from 'zod';

const KOREAN_REGEX = /[가-힣]/;
const KEBAB_REGEX = /^[a-z0-9]+(-[a-z0-9]+)*$/;
const ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;

const RawResponseSchema = z.object({
  title: z.string().trim().min(1).max(200),
  summary: z.string().min(1),
  tags: z.array(z.string()).default([]),
  due_date: z.string().regex(ISO_DATE_REGEX).nullable().optional()
});

export interface AiResponse {
  title: string;
  summary: string;
  tags: string[];
  dueDate: string | null;
}

function normalizeSummary(raw: string): string {
  const lines = raw.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0);
  if (lines.length === 0) throw new Error('summary is empty');
  if (lines.length === 3) return lines.join('\n');
  if (lines.length < 3) {
    while (lines.length < 3) lines.push('');
    return lines.join('\n');
  }
  const head = lines.slice(0, 2);
  const tail = lines.slice(2).join(' ');
  return [...head, tail].join('\n');
}

function validateDueDate(d: string | null | undefined): string | null {
  if (d === null || d === undefined) return null;
  // Re-verify the date is actually valid (regex passes 2026-13-99 which is invalid)
  const dt = new Date(d + 'T00:00:00Z');
  if (Number.isNaN(dt.getTime()) || dt.toISOString().slice(0, 10) !== d) return null;
  return d;
}

/**
 * vision 모델 (gemma4:26b 등) 이 본문 빈 케이스에 title/summary null 반환하는 케이스
 * 대응. null → placeholder 한국어 문자열로 coerce 후 schema 통과. 빈 string / empty regex
 * dueDate 도 null 로 normalize. raw_text 는 호출자가 보존하므로 사용자 데이터 손실 없음.
 */
function coerceNullable(raw: unknown): unknown {
  if (typeof raw !== 'object' || raw === null) return raw;
  const obj = { ...(raw as Record<string, unknown>) };
  if (obj.title === null || obj.title === '') obj.title = '(첨부 메모)';
  if (obj.summary === null || obj.summary === '') obj.summary = '내용을 자동으로 정리하지 못했습니다.';
  // due_date 의 빈 string / regex mismatch 도 null 로 강제 (schema 가 거부하지 않게).
  if (obj.due_date === '' || (typeof obj.due_date === 'string' && !ISO_DATE_REGEX.test(obj.due_date))) {
    obj.due_date = null;
  }
  // tags 가 null 이면 빈 배열로.
  if (obj.tags === null || obj.tags === undefined) obj.tags = [];
  return obj;
}

export function parseAiResponse(raw: unknown): AiResponse {
  const coerced = coerceNullable(raw);
  const parsed = RawResponseSchema.parse(coerced);
  // title 이 한국어 0 자면 fallback placeholder 적용 (영어 title 도 fail 안 함).
  // placeholder 는 한국어 포함이라 자기 자신 통과.
  const titleHasKorean = KOREAN_REGEX.test(parsed.title);
  const finalTitle = titleHasKorean ? parsed.title : '(첨부 메모)';
  return {
    title: finalTitle.slice(0, 60),
    summary: normalizeSummary(parsed.summary),
    tags: parsed.tags.filter((t) => KEBAB_REGEX.test(t)).slice(0, 3),
    dueDate: validateDueDate(parsed.due_date)
  };
}
