import { useEffect, useRef, useState } from "react";
import Button from "../Button";
import { CredentialFields } from "../CredentialPanel";
import DismissibleAlert from "../DismissibleAlert";
import FormField from "../FormField";
import SegmentedControl from "../SegmentedControl";

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 MailServerSettingsSection = "smtp" | "imap";
export type MailServerSettingsMode = "all" | "server" | "credentials";

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;
  busyAction?: "smtp" | "imap" | "folders" | string | null;
  onTestSmtp?: () => void;
  onTestImap?: () => void;
  smtpTestResult?: MailServerConnectionTestResult | null;
  imapTestResult?: MailServerConnectionTestResult | null;
  disabled?: boolean;
  className?: string;
  floatingResults?: boolean;
  initialSection?: MailServerSettingsSection;
  visibleSections?: readonly MailServerSettingsSection[];
  mode?: MailServerSettingsMode;
};

export const mailServerSecurityOptions = ["plain", "tls", "starttls"] as const;
export type MailServerSecurityOption = typeof mailServerSecurityOptions[number];
const securityOptions = mailServerSecurityOptions;

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 function resolveMailServerSettingsActiveSection(
activeSection: MailServerSettingsSection,
initialSection: MailServerSettingsSection,
previousInitialSection: MailServerSettingsSection,
visibleSectionIds: readonly MailServerSettingsSection[])
: MailServerSettingsSection {
  const fallbackSection = visibleSectionIds[0] ?? "smtp";
  const initialSectionVisible = visibleSectionIds.includes(initialSection);
  if (previousInitialSection !== initialSection && initialSectionVisible) return initialSection;
  if (!visibleSectionIds.includes(activeSection)) return initialSectionVisible ? initialSection : fallbackSection;
  return activeSection;
}

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 = "i18n:govoplan-core.test_smtp.e5697981",
  imapTestLabel = "i18n:govoplan-core.test_imap.ef1bd79c",
  busyAction = null,
  onTestSmtp,
  onTestImap,
  smtpTestResult = null,
  imapTestResult = null,
  disabled = false,
  className = "",
  floatingResults = false,
  initialSection = "smtp",
  visibleSections,
  mode = "all"
}: 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 allSections: {id: MailServerSettingsSection;label: string;}[] = [
  { id: "smtp", label: "i18n:govoplan-core.smtp.efff9cca" },
  { id: "imap", label: "i18n:govoplan-core.imap.271f9ef2" }];
  const visibleSectionSet = new Set(visibleSections ?? allSections.map((section) => section.id));
  const sections = allSections.filter((section) => visibleSectionSet.has(section.id));
  const visibleSectionIds = sections.map((section) => section.id);
  const fallbackSection = visibleSectionIds[0] ?? "smtp";
  const resolvedInitialSection = visibleSectionIds.includes(initialSection) ? initialSection : fallbackSection;
  const sectionKey = visibleSectionIds.join("|");
  const [activeSection, setActiveSection] = useState<MailServerSettingsSection>(resolvedInitialSection);
  const previousInitialSectionRef = useRef(initialSection);
  const showSectionSwitcher = sections.length > 1;
  const showServerFields = mode !== "credentials";
  const showCredentialFields = mode !== "server";

  useEffect(() => {
    const nextSection = resolveMailServerSettingsActiveSection(
      activeSection,
      initialSection,
      previousInitialSectionRef.current,
      visibleSectionIds
    );
    previousInitialSectionRef.current = initialSection;
    if (nextSection !== activeSection) setActiveSection(nextSection);
  }, [activeSection, initialSection, sectionKey]);


  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()}>
      {showSectionSwitcher &&
      <SegmentedControl
        className="mail-server-segmented-control"
        size="equal"
        ariaLabel="i18n:govoplan-core.mail_server_settings_sections.40a163b7"
        value={activeSection}
        onChange={setActiveSection}
        options={sections}
      />
      }

      <div className="mail-server-settings-view">
        {activeSection === "smtp" &&
        <section className="mail-server-subsection" role="tabpanel" aria-label="i18n:govoplan-core.smtp_settings.f103e570">
            <div className="form-grid compact responsive-form-grid mail-server-form-grid">
              {showServerFields &&
              <>
              <FormField label="i18n:govoplan-core.server.cb0cb170" help="i18n:govoplan-core.mail_server_hostname_or_ip_address_for_the_selec.596c2d69"><input value={stringValue(smtp.host)} disabled={smtpFieldsDisabled} onChange={(event) => onSmtpChange({ host: event.target.value })} /></FormField>
              <FormField label="i18n:govoplan-core.port.fe035157"><input type="number" min={1} max={65535} value={smtpPort} disabled={smtpFieldsDisabled} onChange={(event) => onSmtpChange({ port: event.target.value })} /></FormField>
              <FormField label="i18n:govoplan-core.security.f25ce1b8"><SecuritySelect value={smtpSecurity} disabled={smtpFieldsDisabled} onChange={patchSmtpSecurity} /></FormField>
              <FormField label="i18n:govoplan-core.timeout_seconds.0bfc6553"><input type="number" min={1} value={stringValue(smtp.timeout_seconds)} disabled={smtpFieldsDisabled} onChange={(event) => onSmtpChange({ timeout_seconds: event.target.value })} /></FormField>
              </>
              }
              {showCredentialFields &&
              <CredentialFields
                values={smtpCredentialValues}
                onChange={patchSmtpCredentials}
                disabled={smtpCredentialFieldsDisabled}
                savedPassword={smtpPasswordSaved}
                savedPasswordPlaceholder={smtpSavedPasswordPlaceholder} />
              }
            </div>
            {onTestSmtp &&
          <div className="button-row compact-actions mail-server-actions">
                <Button type="button" variant="primary" onClick={onTestSmtp} disabled={smtpActionsDisabled || busyAction === "smtp"}>{busyAction === "smtp" ? "i18n:govoplan-core.testing.15ccc832" : smtpTestLabel}</Button>
              </div>
          }
            <MailServerActionResult result={smtpTestResult} floating={floatingResults} />
          </section>
        }

        {activeSection === "imap" &&
        <section className="mail-server-subsection" role="tabpanel" aria-label="i18n:govoplan-core.imap_settings.ab8d8247">
            <div className="form-grid compact responsive-form-grid mail-server-form-grid">
              {showServerFields &&
              <>
              <FormField label="i18n:govoplan-core.server.cb0cb170" help="i18n:govoplan-core.mail_server_hostname_or_ip_address_for_the_selec.596c2d69"><input value={stringValue(imap.host)} disabled={imapFieldsDisabled} onChange={(event) => onImapChange({ host: event.target.value })} /></FormField>
              <FormField label="i18n:govoplan-core.port.fe035157"><input type="number" min={1} max={65535} value={imapPort} disabled={imapFieldsDisabled} onChange={(event) => onImapChange({ port: event.target.value })} /></FormField>
              <FormField label="i18n:govoplan-core.security.f25ce1b8"><SecuritySelect value={imapSecurity} disabled={imapFieldsDisabled} onChange={patchImapSecurity} /></FormField>
              <FormField label="i18n:govoplan-core.timeout_seconds.0bfc6553"><input type="number" min={1} value={stringValue(imap.timeout_seconds)} disabled={imapFieldsDisabled} onChange={(event) => onImapChange({ timeout_seconds: event.target.value })} /></FormField>
              </>
              }
              {showCredentialFields &&
              <CredentialFields
                values={imapCredentialValues}
                onChange={patchImapCredentials}
                disabled={imapCredentialFieldsDisabled}
                savedPassword={imapPasswordSaved}
                savedPasswordPlaceholder={imapSavedPasswordPlaceholder} />
              }
            </div>
            {onTestImap &&
          <div className="button-row compact-actions mail-server-actions">
                <Button type="button" variant="primary" onClick={onTestImap} disabled={imapActionsDisabled || busyAction === "imap"}>{busyAction === "imap" ? "i18n:govoplan-core.testing.15ccc832" : imapTestLabel}</Button>
              </div>
          }
            <MailServerActionResult result={imapTestResult} floating={floatingResults} />
          </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> i18n:govoplan-core.authentication.e665f157 {authenticated ? "i18n:govoplan-core.credentials_accepted.ae8e2629" : "i18n:govoplan-core.not_used.487f8bcd"}.</span>
      }
    </DismissibleAlert>);

}

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

  const folders = result.folders ?? [];
  return (
    <DismissibleAlert tone="success" compact={compact} resetKey={`${result.message}:${result.detected_sent_folder || ""}`}>
      <p>{result.message}</p>
      <p>i18n:govoplan-core.detected_sent_folder.cbf8ec8d <strong>{result.detected_sent_folder || "-"}</strong></p>
      {result.detected_sent_folder && onUseDetected && <Button type="button" onClick={onUseDetected} disabled={disabled}>i18n:govoplan-core.use_detected_folder.5ec4965c</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);
}
