import { useState } from "react";
import type { ApiSettings } from "../../types";
import Button from "../../components/Button";
import Card from "../../components/Card";
import FormField from "../../components/FormField";
import PageTitle from "../../components/PageTitle";
import LoadingFrame from "../../components/LoadingFrame";
import ToggleSwitch from "../../components/ToggleSwitch";
import { listImapFolders, testImapSettings, testSmtpSettings, type MailConnectionTestResponse, type MailImapFolderListResponse, type MailSecurity } from "../../api/mail";
import { useCampaignWorkspaceData } from "./hooks/useCampaignWorkspaceData";
import { useCampaignDraftEditor } from "./hooks/useCampaignDraftEditor";
import { asRecord, isAuditLockedVersion, versionLockReason } from "./utils/campaignView";
import { getBool, getNumber, getText } from "./utils/draftEditor";

const securityOptions = ["plain", "tls", "starttls"];

export default function MailSettingsPage({ settings, campaignId }: { settings: ApiSettings; campaignId: string }) {
  const { data, loading, error, reload, setError } = useCampaignWorkspaceData(settings, campaignId);
  const [smtpTestResult, setSmtpTestResult] = useState<MailConnectionTestResponse | null>(null);
  const [imapTestResult, setImapTestResult] = useState<MailConnectionTestResponse | null>(null);
  const [folderResult, setFolderResult] = useState<MailImapFolderListResponse | null>(null);
  const [mailActionState, setMailActionState] = useState<"smtp" | "imap" | "folders" | null>(null);

  const version = data.currentVersion;
  const locked = isAuditLockedVersion(version);
  const { draft, displayDraft, dirty, saveState, localError, setLocalError, patch, saveDraft } = useCampaignDraftEditor({
    settings,
    campaignId,
    version,
    locked,
    reload,
    setError,
    currentStep: "mail-settings",
    unsavedTitle: "Unsaved server settings",
    unsavedMessage: "Server settings have unsaved changes. Save them before leaving, or discard them and continue."
  });
  const server = asRecord(displayDraft.server);
  const smtp = asRecord(server.smtp);
  const imap = asRecord(server.imap);
  const delivery = asRecord(displayDraft.delivery);
  const imapAppend = asRecord(delivery.imap_append_sent);
  const imapEnabled = getBool(imap, "enabled");
  const imapDisabled = locked || !imapEnabled;




  function toggleImap(enabled: boolean) {
    patch(["server", "imap", "enabled"], enabled);
    if (!enabled) {
      patch(["delivery", "imap_append_sent", "enabled"], false);
    }
  }


  function emptyToNull(value: string, trim = true): string | null {
    const normalized = trim ? value.trim() : value;
    return normalized ? normalized : null;
  }

  function readSecurity(value: string, fallback: MailSecurity): MailSecurity {
    return securityOptions.includes(value as MailSecurity) ? (value as MailSecurity) : fallback;
  }


  function smtpPayload() {
    return {
      host: emptyToNull(getText(smtp, "host")),
      port: getNumber(smtp, "port", 587),
      username: emptyToNull(getText(smtp, "username")),
      password: emptyToNull(getText(smtp, "password"), false),
      security: readSecurity(getText(smtp, "security", "starttls"), "starttls"),
      timeout_seconds: getNumber(smtp, "timeout_seconds", 30)
    };
  }

  function imapPayload() {
    return {
      enabled: true,
      host: emptyToNull(getText(imap, "host")),
      port: getNumber(imap, "port", 993),
      username: emptyToNull(getText(imap, "username")),
      password: emptyToNull(getText(imap, "password"), false),
      security: readSecurity(getText(imap, "security", "tls"), "tls"),
      sent_folder: emptyToNull(getText(imap, "sent_folder", "auto")),
      timeout_seconds: getNumber(imap, "timeout_seconds", 30)
    };
  }

  async function runSmtpTest() {
    if (locked) return;
    setMailActionState("smtp");
    setLocalError("");
    try {
      setSmtpTestResult(await testSmtpSettings(settings, smtpPayload()));
    } catch (err) {
      setSmtpTestResult({ ok: false, protocol: "smtp", message: err instanceof Error ? err.message : String(err), details: {} });
    } finally {
      setMailActionState(null);
    }
  }

  async function runImapTest() {
    if (imapDisabled) return;
    setMailActionState("imap");
    setLocalError("");
    try {
      setImapTestResult(await testImapSettings(settings, imapPayload()));
    } catch (err) {
      setImapTestResult({ ok: false, protocol: "imap", message: err instanceof Error ? err.message : String(err), details: {} });
    } finally {
      setMailActionState(null);
    }
  }

  async function runFolderLookup() {
    if (imapDisabled) return;
    setMailActionState("folders");
    setLocalError("");
    try {
      setFolderResult(await listImapFolders(settings, imapPayload()));
    } catch (err) {
      setFolderResult({ ok: false, protocol: "imap", message: err instanceof Error ? err.message : String(err), folders: [], details: {} });
    } finally {
      setMailActionState(null);
    }
  }

  function useDetectedSentFolder() {
    const folder = folderResult?.detected_sent_folder;
    if (!folder || imapDisabled) return;
    patch(["server", "imap", "sent_folder"], folder);
    if (!getText(imapAppend, "folder") || getText(imapAppend, "folder") === "auto") {
      patch(["delivery", "imap_append_sent", "folder"], folder);
    }
  }

  return (
    <div className="content-pad workspace-data-page">
      <div className="page-heading split workspace-heading">
        <div>
          <PageTitle loading={loading}>Server settings</PageTitle>
          <p className="mono-small">Version {version ? `#${version.version_number}` : "—"} · {saveState}</p>
        </div>
        <div className="button-row compact-actions">
          <Button onClick={reload} disabled={loading}>Reload</Button>
          <Button variant="primary" onClick={() => saveDraft("manual")} disabled={!dirty || locked || !draft}>{dirty ? "Save now" : "Saved"}</Button>
        </div>
      </div>

      {error && <div className="alert danger">{error}</div>}
      {localError && <div className="alert danger">{localError}</div>}
      {locked && <div className="alert info">This version is read-only. {versionLockReason(version)} Copy the campaign before editing server settings.</div>}

      <LoadingFrame loading={loading || !draft} label="Loading campaign draft…">
        <>
          <Card title="Mail server settings">
            <div className="mail-server-settings-grid">
              <section className="form-subsection mail-server-subsection">
                <div className="subsection-heading split">
                  <h3>SMTP login</h3>
                </div>
                <div className="form-grid compact responsive-form-grid">
                  <FormField label="Host"><input value={getText(smtp, "host")} disabled={locked} onChange={(event) => patch(["server", "smtp", "host"], event.target.value)} /></FormField>
                  <FormField label="Port"><input type="number" value={getNumber(smtp, "port", 587)} disabled={locked} onChange={(event) => patch(["server", "smtp", "port"], Number(event.target.value || 0))} /></FormField>
                  <FormField label="Username"><input value={getText(smtp, "username")} disabled={locked} onChange={(event) => patch(["server", "smtp", "username"], event.target.value)} /></FormField>
                  <FormField label="Password"><input type="password" value={getText(smtp, "password")} disabled={locked} onChange={(event) => patch(["server", "smtp", "password"], event.target.value)} /></FormField>
                  <FormField label="Security"><select value={getText(smtp, "security", "starttls")} disabled={locked} onChange={(event) => patch(["server", "smtp", "security"], event.target.value)}>{securityOptions.map((option) => <option key={option}>{option}</option>)}</select></FormField>
                  <FormField label="Timeout seconds"><input type="number" value={getNumber(smtp, "timeout_seconds", 30)} disabled={locked} onChange={(event) => patch(["server", "smtp", "timeout_seconds"], Number(event.target.value || 0))} /></FormField>
                </div>
                <div className="button-row compact-actions subsection-bottom-actions">
                  <Button variant="primary" onClick={runSmtpTest} disabled={locked || mailActionState === "smtp"}>{mailActionState === "smtp" ? "Testing…" : "Test SMTP login"}</Button>
                </div>
                <MailActionResult result={smtpTestResult} />
              </section>

              <section className="form-subsection mail-server-subsection">
                <div className="subsection-heading split">
                  <h3>IMAP sent-folder append</h3>
                </div>
                <div className="form-grid compact responsive-form-grid">
                  <div className="form-span-full toggle-span-full">
                    <ToggleSwitch label="Enable IMAP" checked={imapEnabled} disabled={locked} onChange={toggleImap} />
                  </div>
                  <FormField label="Host"><input value={getText(imap, "host")} disabled={imapDisabled} onChange={(event) => patch(["server", "imap", "host"], event.target.value)} /></FormField>
                  <FormField label="Port"><input type="number" value={getNumber(imap, "port", 993)} disabled={imapDisabled} onChange={(event) => patch(["server", "imap", "port"], Number(event.target.value || 0))} /></FormField>
                  <FormField label="Username"><input value={getText(imap, "username")} disabled={imapDisabled} onChange={(event) => patch(["server", "imap", "username"], event.target.value)} /></FormField>
                  <FormField label="Password"><input type="password" value={getText(imap, "password")} disabled={imapDisabled} onChange={(event) => patch(["server", "imap", "password"], event.target.value)} /></FormField>
                  <FormField label="Security"><select value={getText(imap, "security", "tls")} disabled={imapDisabled} onChange={(event) => patch(["server", "imap", "security"], event.target.value)}>{securityOptions.map((option) => <option key={option}>{option}</option>)}</select></FormField>
                  <FormField label="Detected/saved sent folder"><input value={getText(imap, "sent_folder", "auto")} disabled={imapDisabled} onChange={(event) => patch(["server", "imap", "sent_folder"], event.target.value)} /></FormField>
                  <div className="form-span-full toggle-span-full">
                    <ToggleSwitch label="Append successfully sent messages to Sent" checked={getBool(imapAppend, "enabled")} disabled={imapDisabled} onChange={(checked) => patch(["delivery", "imap_append_sent", "enabled"], checked)} />
                  </div>
                  <FormField label="Append folder"><input value={getText(imapAppend, "folder", getText(imap, "sent_folder", "auto"))} disabled={imapDisabled || !getBool(imapAppend, "enabled")} onChange={(event) => patch(["delivery", "imap_append_sent", "folder"], event.target.value)} /></FormField>
                </div>
                <div className="button-row compact-actions subsection-bottom-actions">
                  <Button variant="primary" onClick={runImapTest} disabled={imapDisabled || mailActionState === "imap"}>{mailActionState === "imap" ? "Testing…" : "Test IMAP login"}</Button>
                  <Button variant="primary" onClick={runFolderLookup} disabled={imapDisabled || mailActionState === "folders"}>{mailActionState === "folders" ? "Looking up…" : "Folders…"}</Button>
                </div>
                <p className="muted small-note">Folder lookup lists visible mailboxes and guesses folders such as Sent, Gesendet or Sent Mail.</p>
                <MailActionResult result={imapTestResult} />
                <FolderLookupResult result={folderResult} disabled={imapDisabled} onUseDetected={useDetectedSentFolder} />
              </section>
            </div>
          </Card>

          <div className="button-row page-bottom-actions">
            <Button variant="primary" onClick={() => saveDraft("manual")} disabled={!dirty || locked}>Save</Button>
          </div>
        </>
      </LoadingFrame>
    </div>
  );
}


function MailActionResult({ result }: { result: MailConnectionTestResponse | null }) {
  if (!result) return null;
  const authenticated = result.details?.authenticated;
  return (
    <div className={`alert ${result.ok ? "success" : "danger"}`}>
      {result.message}
      {result.ok && typeof authenticated === "boolean" && (
        <span> Authentication: {authenticated ? "credentials accepted" : "not used"}.</span>
      )}
    </div>
  );
}

function FolderLookupResult({ result, disabled, onUseDetected }: { result: MailImapFolderListResponse | null; disabled?: boolean; onUseDetected: () => void }) {
  if (!result) return null;
  if (!result.ok) {
    return <div className="alert danger">{result.message}</div>;
  }

  return (
    <div className="alert success">
      <p>{result.message}</p>
      <p>Detected Sent folder: <strong>{result.detected_sent_folder || "—"}</strong></p>
      {result.detected_sent_folder && <Button onClick={onUseDetected} disabled={disabled}>Use detected folder</Button>}
      {result.folders.length > 0 && (
        <div className="field-chip-list">
          {result.folders.slice(0, 12).map((folder) => (
            <span className="field-chip" key={folder.name} title={(folder.flags || []).join(" ")}>{folder.name}</span>
          ))}
          {result.folders.length > 12 && <span className="field-chip">+{result.folders.length - 12} more</span>}
        </div>
      )}
    </div>
  );
}