import "server-only";

import type { ResultSetHeader, RowDataPacket } from "mysql2/promise";
import { ensureOfficialMailSchema, getDbPool } from "@/lib/db";
import { createInternalMailboxNotification } from "@/lib/official-mail";

export const PARTNER_INQUIRY_CONSENT_VERSION = "2026-08-06";

const PLATFORM_TYPES = new Set([
  "coworking",
  "incubator",
  "accelerator",
  "domain-hosting",
  "web-commerce",
  "education-community",
  "saas-api",
  "other",
]);

const PLATFORM_LABELS: Record<string, string> = {
  coworking: "공유오피스·비즈니스센터",
  incubator: "창업보육센터·공공 지원기관",
  accelerator: "액셀러레이터·VC·창업 프로그램",
  "domain-hosting": "도메인 등록·호스팅 사업자",
  "web-commerce": "웹빌더·쇼핑몰·커머스 플랫폼",
  "education-community": "교육기관·창업 커뮤니티",
  "saas-api": "SaaS·API·솔루션 연동",
  other: "기타",
};

const ESTIMATED_MEMBER_LABELS: Record<string, string> = {
  "under-50": "50개사 미만",
  "50-199": "50~199개사",
  "200-499": "200~499개사",
  "500-plus": "500개사 이상",
  unknown: "아직 정해지지 않음",
};

const PARTNER_INQUIRY_NOTIFICATION_EMAIL = (
  process.env.PARTNER_INQUIRY_NOTIFICATION_EMAIL ?? "admin@officialsite.kr"
)
  .trim()
  .toLowerCase();

export type PartnerInquiry = {
  contactEmail: string;
  contactName: string;
  contactPhone: string | null;
  estimatedMembers: string | null;
  id: number;
  message: string | null;
  organizationName: string;
  platformType: string;
  platformTypeCustom: string | null;
};

type RecentInquiryRow = RowDataPacket & {
  recent_count: number;
};

function cleanText(value: unknown, maxLength: number) {
  return String(value ?? "")
    .trim()
    .replace(/[\u0000-\u001f\u007f]/g, "")
    .slice(0, maxLength);
}

function normalizeEmail(value: unknown) {
  const email = cleanText(value, 320).toLowerCase();

  if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
    throw new Error("partner-inquiry-invalid-email");
  }

  return email;
}

export async function createPartnerInquiry(input: {
  organizationName?: unknown;
  contactName?: unknown;
  contactEmail?: unknown;
  contactPhone?: unknown;
  platformType?: unknown;
  platformTypeCustom?: unknown;
  estimatedMembers?: unknown;
  message?: unknown;
  consented?: unknown;
  website?: unknown;
}) {
  await ensureOfficialMailSchema();

  if (cleanText(input.website, 200)) {
    return null;
  }

  const organizationName = cleanText(input.organizationName, 191);
  const contactName = cleanText(input.contactName, 120);
  const contactEmail = normalizeEmail(input.contactEmail);
  const contactPhone = cleanText(input.contactPhone, 40) || null;
  const platformType = cleanText(input.platformType, 64);
  const platformTypeCustom = cleanText(input.platformTypeCustom, 120) || null;
  const estimatedMembers = cleanText(input.estimatedMembers, 32) || null;
  const message = cleanText(input.message, 3000) || null;

  if (!organizationName || !contactName || !PLATFORM_TYPES.has(platformType)) {
    throw new Error("partner-inquiry-required-fields");
  }

  if (platformType === "other" && !platformTypeCustom) {
    throw new Error("partner-inquiry-custom-platform-required");
  }

  if (input.consented !== true) {
    throw new Error("partner-inquiry-consent-required");
  }

  const [recentRows] = await getDbPool().query<RecentInquiryRow[]>(
    `
      SELECT COUNT(*) AS recent_count
      FROM partner_inquiries
      WHERE contact_email = ?
        AND requested_at >= DATE_SUB(NOW(), INTERVAL 10 MINUTE)
    `,
    [contactEmail],
  );

  if (Number(recentRows[0]?.recent_count ?? 0) > 0) {
    throw new Error("partner-inquiry-too-frequent");
  }

  const [result] = await getDbPool().query<ResultSetHeader>(
    `
      INSERT INTO partner_inquiries (
        organization_name,
        contact_name,
        contact_email,
        contact_phone,
        platform_type,
        platform_type_custom,
        estimated_members,
        message,
        consent_version,
        consented_at
      ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())
    `,
    [
      organizationName,
      contactName,
      contactEmail,
      contactPhone,
      platformType,
      platformTypeCustom,
      estimatedMembers,
      message,
      PARTNER_INQUIRY_CONSENT_VERSION,
    ],
  );

  return {
    contactEmail,
    contactName,
    contactPhone,
    estimatedMembers,
    id: result.insertId,
    message,
    organizationName,
    platformType,
    platformTypeCustom,
  } satisfies PartnerInquiry;
}

export async function sendPartnerInquiryNotification(
  inquiry: PartnerInquiry,
) {
  const platformLabel =
    inquiry.platformType === "other"
      ? inquiry.platformTypeCustom || PLATFORM_LABELS.other
      : PLATFORM_LABELS[inquiry.platformType] || inquiry.platformType;
  const estimatedMembersLabel = inquiry.estimatedMembers
    ? ESTIMATED_MEMBER_LABELS[inquiry.estimatedMembers] || inquiry.estimatedMembers
    : "미입력";
  const bodyText = [
    "새로운 제휴 문의가 접수되었습니다.",
    "",
    `문의 번호: #${inquiry.id}`,
    `기관·회사명: ${inquiry.organizationName}`,
    `담당자명: ${inquiry.contactName}`,
    `담당자 이메일: ${inquiry.contactEmail}`,
    `연락처: ${inquiry.contactPhone || "미입력"}`,
    `제휴 플랫폼: ${platformLabel}`,
    `예상 지원 규모: ${estimatedMembersLabel}`,
    "",
    "제휴 목적·운영 방식",
    inquiry.message || "미입력",
    "",
    "이 메일에 답장하면 문의 담당자 이메일로 회신됩니다.",
  ].join("\n");

  try {
    await createInternalMailboxNotification({
      bodyText,
      fromAddress: inquiry.contactEmail,
      fromName: inquiry.contactName,
      notificationKey: `partner-inquiry:${inquiry.id}`,
      recipientEmail: PARTNER_INQUIRY_NOTIFICATION_EMAIL,
      subject: `[제휴 문의] ${inquiry.organizationName} · ${inquiry.contactName}`,
    });
    await getDbPool().query(
      `
        UPDATE partner_inquiries
        SET
          notification_status = 'sent',
          notification_sent_at = NOW(),
          notification_error = NULL,
          updated_at = NOW()
        WHERE id = ?
      `,
      [inquiry.id],
    );
  } catch (error) {
    const message = cleanText(
      error instanceof Error ? error.message : "unknown-error",
      255,
    );

    await getDbPool()
      .query(
        `
          UPDATE partner_inquiries
          SET
            notification_status = 'failed',
            notification_error = ?,
            updated_at = NOW()
          WHERE id = ?
        `,
        [message, inquiry.id],
      )
      .catch(() => {});

    throw error;
  }
}
