import { useState } from "react";
import Button from "../Button";
import DismissibleAlert from "../DismissibleAlert";
import FormField from "../FormField";
import PasswordField from "../PasswordField";
import ToggleSwitch from "../ToggleSwitch";

export type MailServerSecurity = "plain" | "tls" | "starttls" | string;

export type MailServerCredentialSettings = {
  username?: string | null;
  password?: string | null;
};

export type MailServerSmtpSettings = {
  host?: string | null;
  port?: string | number | null;
  security?: MailServerSecurity | null;
  timeout_seconds?: string | number | null;
  username?: string | null;
  password?: string | null;
};

export type MailServerImapSettings = MailServerSmtpSettings & {
  sent_folder?: string | null;
};

export type MailServerConnectionTestResult = {
  ok: boolean;
  protocol?: "smtp" | "imap";
  host?: string | null;
  port?: number | null;
  security?: MailServerSecurity | null;
  message: string;
  details?: Record<string, unknown> | null;
};

export type MailServerFolderLookupResult = {
  ok: boolean;
  protocol?: "imap";
  host?: string | null;
  port?: number | null;
  security?: MailServerSecurity | null;
  message: string;
  detected_sent_folder?: string | null;
  folders?: { name: string; flags?: string[] }[];
  details?: Record<string, unknown> | null;
};

export type MailServerSettingsPanelProps = {
  smtp: MailServerSmtpSettings;
  imap: MailServerImapSettings;
  onSmtpChange: (patch: Partial<MailServerSmtpSettings>) => void;
  onImapChange: (patch: Partial<MailServerImapSettings>) => void;
  smtpCredentials?: MailServerCredentialSettings;
  imapCredentials?: MailServerCredentialSettings;
  onSmtpCredentialsChange?: (patch: Partial<MailServerCredentialSettings>) => void;
  onImapCredentialsChange?: (patch: Partial<MailServerCredentialSettings>) => void;
  smtpDisabled?: boolean;
  smtpCredentialDisabled?: boolean;
  smtpPasswordSaved?: boolean;
  smtpSavedPasswordPlaceholder?: string;
  smtpActionDisabled?: boolean;
  imapServerDisabled?: boolean;
  imapCredentialDisabled?: boolean;
  imapPasswordSaved?: boolean;
  imapSavedPasswordPlaceholder?: string;
  imapActionDisabled?: boolean;
  smtpTestLabel?: string;
  imapTestLabel?: string;
  folderLookupLabel?: string;
  busyAction?: "smtp" | "imap" | "folders" | string | null;
  onTestSmtp?: () => void;
  onTestImap?: () => void;
  onLookupFolders?: () => void;
  smtpTestResult?: MailServerConnectionTestResult | null;
  imapTestResult?: MailServerConnectionTestResult | null;
  folderLookupResult?: MailServerFolderLookupResult | null;
  onUseDetectedFolder?: () => void;
  useDetectedFolderDisabled?: boolean;
  mockToggle?: {
    label?: string;
    checked: boolean;
    disabled?: boolean;
    onChange: (checked: boolean) => void;
  };
  append?: {
    enabled: boolean;
    folder: string;
    disabled?: boolean;
    folderDisabled?: boolean;
    onEnabledChange: (enabled: boolean) => void;
    onFolderChange: (folder: string) => void;
  };
  disabled?: boolean;
  className?: string;
  floatingResults?: boolean;
  initialSection?: MailServerSettingsSection;
};

export const mailServerSecurityOptions = ["plain", "tls", "starttls"] as const;
export type MailServerSecurityOption = typeof mailServerSecurityOptions[number];
const securityOptions = mailServerSecurityOptions;
type MailServerSettingsSection = "smtp" | "imap" | "advanced";

export function defaultSmtpPort(security: MailServerSecurity | null | undefined): number {
  if (security === "tls") return 465;
  if (security === "plain") return 25;
  return 587;
}

export function defaultImapPort(security: MailServerSecurity | null | undefined): number {
  return security === "tls" ? 993 : 143;
}


export function mailTextOrNull(value: string | number | null | undefined, trim = true): string | null {
  const text = value === null || value === undefined ? "" : String(value);
  const normalized = trim ? text.trim() : text;
  return normalized ? normalized : null;
}

export function mailNumberOrNull(value: string | number | null | undefined): number | null {
  if (typeof value === "number") return Number.isFinite(value) ? value : null;
  const text = String(value ?? "").trim();
  if (!text) return null;
  const parsed = Number(text);
  return Number.isFinite(parsed) ? parsed : null;
}

export function mailNumberOrDefault(value: string | number | null | undefined, fallback: number): number {
  return mailNumberOrNull(value) ?? fallback;
}

export function normalizeMailServerSecurity<TSecurity extends string = MailServerSecurityOption>(
  value: string | null | undefined,
  options: { fallback: TSecurity; allowedSecurity?: readonly TSecurity[] },
): TSecurity {
  const allowed = options.allowedSecurity ?? (mailServerSecurityOptions as unknown as readonly TSecurity[]);
  return allowed.includes(value as TSecurity) ? (value as TSecurity) : options.fallback;
}

export function mailTransportCredentialsPayload(
  username: string | number | null | undefined,
  password: string | number | null | undefined,
  preserveBlankPassword: boolean,
): { username?: string | null; password?: string | null } {
  const payload: { username?: string | null; password?: string | null } = { username: mailTextOrNull(username) };
  if (String(password ?? "") || !preserveBlankPassword) payload.password = mailTextOrNull(password, false);
  return payload;
}

function mailRecordText(record: Record<string, unknown>, key: string, fallback = ""): string {
  const value = record[key];
  if (value === null || value === undefined) return fallback;
  return String(value);
}

export function mailTransportCredentialsPayloadFromRecords(
  primary: Record<string, unknown>,
  legacy: Record<string, unknown>,
  preserveBlankPassword: boolean,
): { username?: string | null; password?: string | null } {
  return mailTransportCredentialsPayload(
    mailRecordText(primary, "username", mailRecordText(legacy, "username")),
    mailRecordText(primary, "password", mailRecordText(legacy, "password")),
    preserveBlankPassword,
  );
}

export function mailSmtpSettingsPayload<TSecurity extends string = MailServerSecurityOption>(
  settings: MailServerSmtpSettings,
  options: { fallbackSecurity: TSecurity; allowedSecurity?: readonly TSecurity[]; fallbackTimeoutSeconds?: number },
): { host: string | null; port: number | null; security: TSecurity; timeout_seconds: number } {
  return {
    host: mailTextOrNull(settings.host),
    port: mailNumberOrNull(settings.port),
    security: normalizeMailServerSecurity(settings.security ? String(settings.security) : null, { fallback: options.fallbackSecurity, allowedSecurity: options.allowedSecurity }),
    timeout_seconds: mailNumberOrDefault(settings.timeout_seconds, options.fallbackTimeoutSeconds ?? 30),
  };
}

export function mailImapSettingsPayload<TSecurity extends string = MailServerSecurityOption>(
  settings: MailServerImapSettings,
  options: { fallbackSecurity: TSecurity; allowedSecurity?: readonly TSecurity[]; fallbackTimeoutSeconds?: number },
): { host: string | null; port: number | null; security: TSecurity; sent_folder: string; timeout_seconds: number } {
  return {
    host: mailTextOrNull(settings.host),
    port: mailNumberOrNull(settings.port),
    security: normalizeMailServerSecurity(settings.security ? String(settings.security) : null, { fallback: options.fallbackSecurity, allowedSecurity: options.allowedSecurity }),
    sent_folder: mailTextOrNull(settings.sent_folder) || "auto",
    timeout_seconds: mailNumberOrDefault(settings.timeout_seconds, options.fallbackTimeoutSeconds ?? 30),
  };
}

export function hasMailImapSettings(values: Array<string | number | null | undefined>): boolean {
  return values.some((value) => String(value ?? "").trim() !== "");
}

export default function MailServerSettingsPanel({
  smtp,
  imap,
  onSmtpChange,
  onImapChange,
  smtpCredentials,
  imapCredentials,
  onSmtpCredentialsChange,
  onImapCredentialsChange,
  smtpDisabled = false,
  smtpCredentialDisabled = smtpDisabled,
  smtpPasswordSaved = false,
  smtpSavedPasswordPlaceholder = "••••••••",
  smtpActionDisabled = smtpDisabled,
  imapServerDisabled = false,
  imapCredentialDisabled = imapServerDisabled,
  imapPasswordSaved = false,
  imapSavedPasswordPlaceholder = "••••••••",
  imapActionDisabled = imapServerDisabled,
  smtpTestLabel = "Test SMTP",
  imapTestLabel = "Test IMAP",
  folderLookupLabel = "Folders...",
  busyAction = null,
  onTestSmtp,
  onTestImap,
  onLookupFolders,
  smtpTestResult = null,
  imapTestResult = null,
  folderLookupResult = null,
  onUseDetectedFolder,
  useDetectedFolderDisabled = false,
  mockToggle,
  append,
  disabled = false,
  className = "",
  floatingResults = false,
  initialSection = "smtp"
}: MailServerSettingsPanelProps) {
  const smtpFieldsDisabled = disabled || smtpDisabled;
  const smtpCredentialFieldsDisabled = disabled || smtpCredentialDisabled;
  const smtpActionsDisabled = disabled || smtpActionDisabled;
  const imapFieldsDisabled = disabled || imapServerDisabled;
  const imapCredentialFieldsDisabled = disabled || imapCredentialDisabled;
  const imapActionsDisabled = disabled || imapActionDisabled;
  const smtpCredentialValues = smtpCredentials ?? { username: smtp.username, password: smtp.password };
  const imapCredentialValues = imapCredentials ?? { username: imap.username, password: imap.password };
  const smtpSecurity = stringValue(smtp.security, "starttls");
  const imapSecurity = stringValue(imap.security, "tls");
  const smtpPort = stringValue(smtp.port, String(defaultSmtpPort(smtpSecurity)));
  const imapPort = stringValue(imap.port, String(defaultImapPort(imapSecurity)));
  const appendTargetFolder = append ? append.folder : stringValue(imap.sent_folder, "auto");
  const appendTargetDisabled = append ? disabled || append.folderDisabled : imapFieldsDisabled;
  const canLookupAppendFolders = Boolean(onLookupFolders) && !appendTargetDisabled;
  const appendTargetHelp = append
    ? "Folder for sent-message copies. Leave as auto unless this campaign needs a different target."
    : "Folder used when this IMAP account is used for sent-message copies. Leave as auto to use the server default.";
  const [activeSection, setActiveSection] = useState<MailServerSettingsSection>(initialSection);
  const sections: { id: MailServerSettingsSection; label: string }[] = [
    { id: "smtp", label: "SMTP" },
    { id: "imap", label: "IMAP" },
    { id: "advanced", label: "Advanced" }
  ];

  function patchSmtpSecurity(security: MailServerSecurity) {
    const port = portForSecurityChange("smtp", smtp.port, smtpSecurity, security);
    onSmtpChange(port === undefined ? { security } : { security, port });
  }

  function patchImapSecurity(security: MailServerSecurity) {
    const port = portForSecurityChange("imap", imap.port, imapSecurity, security);
    onImapChange(port === undefined ? { security } : { security, port });
  }

  function patchSmtpCredentials(patch: Partial<MailServerCredentialSettings>) {
    if (onSmtpCredentialsChange) onSmtpCredentialsChange(patch);
    else onSmtpChange(patch);
  }

  function patchImapCredentials(patch: Partial<MailServerCredentialSettings>) {
    if (onImapCredentialsChange) onImapCredentialsChange(patch);
    else onImapChange(patch);
  }

  return (
    <div className={`mail-server-settings-panel ${className}`.trim()}>
      <div className="mail-server-segmented-control" role="tablist" aria-label="Mail server settings sections">
        {sections.map((section) => (
          <button
            type="button"
            key={section.id}
            role="tab"
            aria-selected={activeSection === section.id}
            className={`mail-server-segmented-tab${activeSection === section.id ? " is-active" : ""}`}
            onClick={() => setActiveSection(section.id)}
          >
            {section.label}
          </button>
        ))}
      </div>

      <div className="mail-server-settings-view">
        {activeSection === "smtp" && (
          <section className="mail-server-subsection" role="tabpanel" aria-label="SMTP settings">
            <div className="form-grid compact responsive-form-grid mail-server-form-grid">
              <div className="mail-server-field-heading">Server</div>
              <FormField label="Host"><input value={stringValue(smtp.host)} disabled={smtpFieldsDisabled} onChange={(event) => onSmtpChange({ host: event.target.value })} /></FormField>
              <FormField label="Port"><input type="number" min={1} max={65535} value={smtpPort} disabled={smtpFieldsDisabled} onChange={(event) => onSmtpChange({ port: event.target.value })} /></FormField>
              <FormField label="Security"><SecuritySelect value={smtpSecurity} disabled={smtpFieldsDisabled} onChange={patchSmtpSecurity} /></FormField>
              <div className="mail-server-field-heading">Credentials</div>
              <FormField label="Username"><input value={stringValue(smtpCredentialValues.username)} disabled={smtpCredentialFieldsDisabled} onChange={(event) => patchSmtpCredentials({ username: event.target.value })} /></FormField>
              <FormField label="Password">
                <PasswordField
                  value={stringValue(smtpCredentialValues.password)}
                  disabled={smtpCredentialFieldsDisabled}
                  saved={smtpPasswordSaved}
                  savedPlaceholder={smtpSavedPasswordPlaceholder}
                  autoComplete="new-password"
                  onValueChange={(password) => patchSmtpCredentials({ password })}
                />
              </FormField>
            </div>
            {onTestSmtp && (
              <div className="button-row compact-actions mail-server-actions">
                <Button type="button" variant="primary" onClick={onTestSmtp} disabled={smtpActionsDisabled || busyAction === "smtp"}>{busyAction === "smtp" ? "Testing..." : smtpTestLabel}</Button>
              </div>
            )}
            <MailServerActionResult result={smtpTestResult} floating={floatingResults} />
          </section>
        )}

        {activeSection === "imap" && (
          <section className="mail-server-subsection" role="tabpanel" aria-label="IMAP settings">
            <div className="form-grid compact responsive-form-grid mail-server-form-grid">
              <div className="mail-server-field-heading">Server</div>
              <FormField label="Host"><input value={stringValue(imap.host)} disabled={imapFieldsDisabled} onChange={(event) => onImapChange({ host: event.target.value })} /></FormField>
              <FormField label="Port"><input type="number" min={1} max={65535} value={imapPort} disabled={imapFieldsDisabled} onChange={(event) => onImapChange({ port: event.target.value })} /></FormField>
              <FormField label="Security"><SecuritySelect value={imapSecurity} disabled={imapFieldsDisabled} onChange={patchImapSecurity} /></FormField>
              <div className="mail-server-field-heading">Credentials</div>
              <FormField label="Username"><input value={stringValue(imapCredentialValues.username)} disabled={imapCredentialFieldsDisabled} onChange={(event) => patchImapCredentials({ username: event.target.value })} /></FormField>
              <FormField label="Password">
                <PasswordField
                  value={stringValue(imapCredentialValues.password)}
                  disabled={imapCredentialFieldsDisabled}
                  saved={imapPasswordSaved}
                  savedPlaceholder={imapSavedPasswordPlaceholder}
                  autoComplete="new-password"
                  onValueChange={(password) => patchImapCredentials({ password })}
                />
              </FormField>
            </div>
            {onTestImap && (
              <div className="button-row compact-actions mail-server-actions">
                <Button type="button" variant="primary" onClick={onTestImap} disabled={imapActionsDisabled || busyAction === "imap"}>{busyAction === "imap" ? "Testing..." : imapTestLabel}</Button>
              </div>
            )}
            <MailServerActionResult result={imapTestResult} floating={floatingResults} />
          </section>
        )}

        {activeSection === "advanced" && (
          <section className="mail-server-subsection" role="tabpanel" aria-label="Advanced mail settings">
            <div className="form-grid compact responsive-form-grid mail-server-form-grid mail-server-advanced-grid">
              {mockToggle && (
                <div className="mail-server-field-span mail-server-toggle-row">
                  <ToggleSwitch
                    label={mockToggle.label ?? "Mock server settings"}
                    checked={mockToggle.checked}
                    disabled={disabled || mockToggle.disabled}
                    onChange={mockToggle.onChange}
                  />
                </div>
              )}
              <FormField label="SMTP timeout seconds"><input type="number" min={1} value={stringValue(smtp.timeout_seconds)} disabled={smtpFieldsDisabled} onChange={(event) => onSmtpChange({ timeout_seconds: event.target.value })} /></FormField>
              <FormField label="IMAP timeout seconds"><input type="number" min={1} value={stringValue(imap.timeout_seconds)} disabled={imapFieldsDisabled} onChange={(event) => onImapChange({ timeout_seconds: event.target.value })} /></FormField>
              {append && (
                <div className="mail-server-field-span mail-server-toggle-row mail-server-plain-toggle-row">
                  <ToggleSwitch label="Append successfully sent messages to Sent" checked={append.enabled} disabled={disabled || append.disabled} onChange={append.onEnabledChange} />
                </div>
              )}
              <FormField label="Append target folder" help={appendTargetHelp}>
                <div className="field-with-action mail-server-folder-field">
                  <input
                    value={appendTargetFolder}
                    disabled={appendTargetDisabled}
                    onChange={(event) => append ? append.onFolderChange(event.target.value) : onImapChange({ sent_folder: event.target.value })}
                    placeholder="auto"
                  />
                  {canLookupAppendFolders && <Button type="button" variant="primary" onClick={onLookupFolders} disabled={imapActionsDisabled || busyAction === "folders"}>{busyAction === "folders" ? "Looking up..." : folderLookupLabel}</Button>}
                </div>
              </FormField>
              {canLookupAppendFolders && <MailServerFolderLookupResultView result={folderLookupResult} disabled={useDetectedFolderDisabled || appendTargetDisabled} onUseDetected={onUseDetectedFolder} />}
            </div>
          </section>
        )}
      </div>
    </div>
  );
}

export function MailServerActionResult({ result, floating = false }: { result: MailServerConnectionTestResult | null | undefined; floating?: boolean }) {
  if (!result) return null;
  const authenticated = result.details?.authenticated;
  return (
    <DismissibleAlert tone={result.ok ? "success" : "danger"} resetKey={`${result.ok}:${result.message}`} floating={floating}>
      {result.message}
      {result.ok && typeof authenticated === "boolean" && (
        <span> Authentication: {authenticated ? "credentials accepted" : "not used"}.</span>
      )}
    </DismissibleAlert>
  );
}

export function MailServerFolderLookupResultView({
  result,
  disabled = false,
  onUseDetected
}: {
  result: MailServerFolderLookupResult | null | undefined;
  disabled?: boolean;
  onUseDetected?: () => void;
}) {
  if (!result) return null;
  if (!result.ok) {
    return <DismissibleAlert tone="danger" resetKey={result.message}>{result.message}</DismissibleAlert>;
  }

  const folders = result.folders ?? [];
  return (
    <DismissibleAlert tone="success" resetKey={`${result.message}:${result.detected_sent_folder || ""}`}>
      <p>{result.message}</p>
      <p>Detected Sent folder: <strong>{result.detected_sent_folder || "-"}</strong></p>
      {result.detected_sent_folder && onUseDetected && <Button type="button" onClick={onUseDetected} disabled={disabled}>Use detected folder</Button>}
      {folders.length > 0 && (
        <div className="mail-server-folder-chip-list">
          {folders.slice(0, 12).map((folder) => (
            <span className="mail-server-folder-chip" key={folder.name} title={(folder.flags || []).join(" ")}>{folder.name}</span>
          ))}
          {folders.length > 12 && <span className="mail-server-folder-chip">+{folders.length - 12} more</span>}
        </div>
      )}
    </DismissibleAlert>
  );
}

function SecuritySelect({ value, disabled, onChange }: { value: string; disabled: boolean; onChange: (value: MailServerSecurity) => void }) {
  return <select value={value} disabled={disabled} onChange={(event) => onChange(event.target.value)}>{securityOptions.map((option) => <option key={option} value={option}>{option}</option>)}</select>;
}

function portForSecurityChange(protocol: "smtp" | "imap", currentPort: string | number | null | undefined, currentSecurity: MailServerSecurity, nextSecurity: MailServerSecurity): number | undefined {
  const current = numberValue(currentPort);
  const previousDefault = protocol === "smtp" ? defaultSmtpPort(currentSecurity) : defaultImapPort(currentSecurity);
  if (current !== null && current !== previousDefault) return undefined;
  return protocol === "smtp" ? defaultSmtpPort(nextSecurity) : defaultImapPort(nextSecurity);
}

function numberValue(value: string | number | null | undefined): number | null {
  if (typeof value === "number") return Number.isFinite(value) ? value : null;
  const trimmed = String(value ?? "").trim();
  if (!trimmed) return null;
  const parsed = Number(trimmed);
  return Number.isFinite(parsed) ? parsed : null;
}

function stringValue(value: string | number | null | undefined, fallback = ""): string {
  if (value === null || value === undefined) return fallback;
  return String(value);
}
