import {
  DEMO_EMAILS,
  DEMO_USER,
  type DemoEmail,
} from "@/components/demo/demo-mail-data"
import type {
  ApiMailAccount,
  ApiMessageFull,
  ApiMessageSummary,
  MessageSearchFilter,
  PaginatedResponse,
  Recipient,
} from "@/lib/api/types"
import { apiMessageToEmail } from "@/lib/demo/demo-mail-email-map"
import { emailMatchesFolder } from "@/lib/mail-folder-filter"
import type { Email } from "@/lib/email-data"
import { normalizeListPageSize } from "@/lib/mail-list-page-size"

export const DEMO_MAIL_ACCOUNT_ID = "demo-mail-account"

export const DEMO_MAIL_ACCOUNT: ApiMailAccount = {
  id: DEMO_MAIL_ACCOUNT_ID,
  name: DEMO_USER.name,
  email: DEMO_USER.email,
  provider: "demo",
  imap_host: "demo.local",
  smtp_host: "demo.local",
  is_active: true,
  created_at: "2026-06-01T08:00:00+02:00",
}

function escapeHtml(text: string): string {
  return text
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
}

function demoTimeToIso(time: string): string {
  const now = new Date()
  const base = new Date(now.getFullYear(), now.getMonth(), now.getDate())
  if (time.includes(":")) {
    const [h, m] = time.split(":").map(Number)
    base.setHours(h, m ?? 0, 0, 0)
    return base.toISOString()
  }
  if (time === "Hier") {
    base.setDate(base.getDate() - 1)
    base.setHours(14, 20, 0, 0)
    return base.toISOString()
  }
  if (time === "Dim.") {
    const day = base.getDay()
    const diff = day === 0 ? 0 : day
    base.setDate(base.getDate() - diff)
    base.setHours(3, 0, 0, 0)
    return base.toISOString()
  }
  if (time.startsWith("Lun")) {
    const day = base.getDay()
    const diff = day === 0 ? 6 : day - 1
    base.setDate(base.getDate() - diff)
    base.setHours(11, 0, 0, 0)
    return base.toISOString()
  }
  const weekdayOffsets: Record<string, number> = {
    "Mar.": 2,
    "Mer.": 3,
    "Jeu.": 4,
    "Ven.": 5,
    "Sam.": 6,
  }
  for (const [prefix, weekday] of Object.entries(weekdayOffsets)) {
    if (time.startsWith(prefix)) {
      const day = base.getDay()
      const diff = day >= weekday ? day - weekday : day + (7 - weekday)
      base.setDate(base.getDate() - diff)
      base.setHours(10, 30, 0, 0)
      return base.toISOString()
    }
  }
  base.setHours(12, 0, 0, 0)
  return base.toISOString()
}

function dedupeLabels(labels: string[]): string[] {
  const seen = new Set<string>()
  const out: string[] = []
  for (const label of labels) {
    const key = label.toLowerCase()
    if (seen.has(key)) continue
    seen.add(key)
    out.push(label)
  }
  return out
}

function demoTagLabels(email: DemoEmail): string[] {
  const tags = [...(email.tags ?? [])]
  if (
    email.label &&
    !tags.some((tag) => tag.toLowerCase() === email.label!.text.toLowerCase())
  ) {
    tags.push(email.label.text)
  }
  return tags
}

function demoFolderToLabels(email: DemoEmail): string[] {
  const tags = demoTagLabels(email)
  if (email.folder === "trash") return ["trash"]
  if (email.folder === "sent") return ["sent"]
  if (email.folder === "drafts") return ["drafts"]
  if (email.folder === "archive") return dedupeLabels(tags)
  return dedupeLabels(["inbox", ...tags])
}

function demoBodyToHtml(body: string[]): string {
  return body
    .map(
      (paragraph) =>
        `<p style="margin:0 0 1em;line-height:1.6;">${escapeHtml(paragraph).replace(/\n/g, "<br>")}</p>`
    )
    .join("")
}

export function demoEmailToApiMessage(email: DemoEmail): ApiMessageFull {
  const flags: string[] = []
  if (!email.unread) flags.push("\\Seen")
  if (email.starred) flags.push("\\Flagged")
  if (email.important) flags.push("important")

  return {
    id: email.id,
    message_id: email.id,
    thread_id: email.id,
    account_id: DEMO_MAIL_ACCOUNT_ID,
    subject: email.subject,
    from: [{ name: email.fromName, address: email.fromEmail }],
    to: [{ name: DEMO_USER.name, address: DEMO_USER.email }],
    date: demoTimeToIso(email.time),
    snippet: email.preview,
    flags,
    labels: demoFolderToLabels(email),
    has_attachments: email.hasAttachment ?? false,
    body_html: demoBodyToHtml(email.body),
    body_text: email.body.join("\n\n"),
  }
}

export function createInitialDemoMessages(): ApiMessageFull[] {
  return DEMO_EMAILS.map(demoEmailToApiMessage)
}

function toSummary(message: ApiMessageFull): ApiMessageSummary {
  const { body_html: _bodyHtml, body_text: _bodyText, cc: _cc, reply_to: _replyTo, auth_info: _auth, in_reply_to: _inReply, references: _refs, ...summary } = message
  return summary
}

function messageToEmail(message: ApiMessageSummary | ApiMessageFull): Email {
  return apiMessageToEmail(message)
}

function matchesSearch(message: ApiMessageSummary, filter: MessageSearchFilter): boolean {
  const email = messageToEmail(message)
  const q = filter.q?.trim().toLowerCase()
  if (q) {
    const haystack = [
      email.sender,
      email.senderEmail ?? "",
      email.subject,
      email.preview,
      message.snippet,
    ]
      .join(" ")
      .toLowerCase()
    if (!haystack.includes(q)) return false
  }
  if (filter.from) {
    const from = filter.from.toLowerCase()
    const sender = message.from[0]?.address?.toLowerCase() ?? ""
    const name = message.from[0]?.name?.toLowerCase() ?? ""
    if (!sender.includes(from) && !name.includes(from)) return false
  }
  if (filter.label) {
    const needle = filter.label.toLowerCase()
    if (!message.labels.some((l) => l.toLowerCase() === needle)) return false
  }
  return true
}

export function listDemoMessages(
  messages: ApiMessageFull[],
  folder: string,
  page: number,
  pageSize: number
): PaginatedResponse<ApiMessageSummary> {
  const safePageSize = normalizeListPageSize(pageSize)
  const ctx = { starredEmailIds: [], importantEmailIds: [] }
  const filtered = messages
    .map(toSummary)
    .filter((message) =>
      emailMatchesFolder(messageToEmail(message), folder, ctx)
    )
    .sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime())

  const start = (page - 1) * safePageSize
  const slice = filtered.slice(start, start + safePageSize)

  return {
    data: slice,
    pagination: {
      page,
      page_size: safePageSize,
      total: filtered.length,
    },
  }
}

export function searchDemoMessages(
  messages: ApiMessageFull[],
  filter: MessageSearchFilter | null,
  page = 1,
  pageSize = 50
): PaginatedResponse<ApiMessageSummary> {
  const safePageSize = normalizeListPageSize(pageSize)
  const filtered = messages
    .map(toSummary)
    .filter((message) => (filter ? matchesSearch(message, filter) : true))
    .sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime())

  const start = (page - 1) * safePageSize
  return {
    data: filtered.slice(start, start + safePageSize),
    pagination: {
      page,
      page_size: safePageSize,
      total: filtered.length,
    },
  }
}

export function demoSentMessageFromPayload(payload: {
  account_id: string
  to: Recipient[]
  subject: string
  body_html: string
}): ApiMessageFull {
  const id = `sent-${Date.now()}`
  const text = payload.body_html.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim()
  return {
    id,
    message_id: id,
    thread_id: id,
    account_id: payload.account_id,
    subject: payload.subject || "(Sans objet)",
    from: [{ name: DEMO_USER.name, address: DEMO_USER.email }],
    to: payload.to,
    date: new Date().toISOString(),
    snippet: text.slice(0, 160) || "(message vide)",
    flags: ["\\Seen"],
    labels: ["sent"],
    has_attachments: false,
    body_html: payload.body_html,
    body_text: text,
  }
}

export function moveDemoMessageToTrash(message: ApiMessageFull): ApiMessageFull {
  const labels = message.labels.filter((l) => l.toLowerCase() !== "inbox")
  if (!labels.some((l) => l.toLowerCase() === "trash")) {
    labels.push("trash")
  }
  return { ...message, labels }
}
