import { useState, useEffect, useRef, useCallback, useMemo } from 'react';
import { Mail, Users, Wifi, Server, Copy, CheckCheck, Settings as SettingsIcon, CheckCircle, XCircle } from 'lucide-react';
import { emailAPI, cellAPI, peerAPI } from '../../services/api';
import { useConfig } from '../../contexts/ConfigContext';
import { useDraftConfig } from '../../contexts/DraftConfigContext';
import { useAuth } from '../../contexts/AuthContext';
import { Field, TextInput, NumberInput } from '../../components/FormFields';
import { detectPortConflicts, validateEmailConfig, PORT_CONFLICT_FIELDS } from '../../utils/serviceConfig';
import ServiceAccountsPanel from '../../components/ServiceAccountsPanel';

const EMAIL_DEFAULTS = { domain: '', smtp_port: 25, submission_port: 587, imap_port: 993, webmail_port: 8888 };

function CopyButton({ text }) {
  const [copied, setCopied] = useState(false);
  return (
    <button
      onClick={() => { navigator.clipboard.writeText(text); setCopied(true); setTimeout(() => setCopied(false), 1500); }}
      className="ml-2 text-gray-400 hover:text-gray-600" title="Copy"
    >
      {copied ? <CheckCheck className="h-3.5 w-3.5 text-green-500" /> : <Copy className="h-3.5 w-3.5" />}
    </button>
  );
}

function InfoRow({ label, value }) {
  return (
    <div className="flex items-center justify-between py-1.5 border-b border-gray-100 last:border-0">
      <span className="text-sm text-gray-500 w-36 shrink-0">{label}</span>
      <div className="flex items-center">
        <span className="text-sm font-mono font-medium text-gray-800">{value}</span>
        <CopyButton text={String(value)} />
      </div>
    </div>
  );
}

function AdminConfigSection({ emailCfg, onChange, errors, portConflicts, saving }) {
  const conflictFor = (f) => portConflicts[`email|${f}`];
  return (
    <div className="card mt-6">
      <div className="flex items-center gap-2 mb-4">
        <SettingsIcon className="h-5 w-5 text-primary-500" />
        <h3 className="text-lg font-medium text-gray-900">Service Configuration</h3>
        {saving && <span className="ml-auto text-xs text-gray-400">Saving…</span>}
      </div>
      <div className="space-y-3">
        <Field label="Mail Domain" error={errors.domain}>
          <TextInput value={emailCfg.domain} onChange={(v) => onChange({ ...emailCfg, domain: v })} placeholder="mail.example.com" />
        </Field>
        <Field label="SMTP Port" hint="MTA-to-MTA (default 25)" error={errors.smtp_port || conflictFor('smtp_port')}>
          <NumberInput value={emailCfg.smtp_port ?? 25} onChange={(v) => onChange({ ...emailCfg, smtp_port: v })} min={1} max={65535} />
        </Field>
        <Field label="Submission Port" hint="Client mail send (default 587)" error={errors.submission_port || conflictFor('submission_port')}>
          <NumberInput value={emailCfg.submission_port ?? 587} onChange={(v) => onChange({ ...emailCfg, submission_port: v })} min={1} max={65535} />
        </Field>
        <Field label="IMAP Port" hint="Client mail fetch (default 993)" error={errors.imap_port || conflictFor('imap_port')}>
          <NumberInput value={emailCfg.imap_port ?? 993} onChange={(v) => onChange({ ...emailCfg, imap_port: v })} min={1} max={65535} />
        </Field>
        <Field label="Webmail Port" hint="Rainloop webmail UI (default 8888)" error={errors.webmail_port || conflictFor('webmail_port')}>
          <NumberInput value={emailCfg.webmail_port ?? 8888} onChange={(v) => onChange({ ...emailCfg, webmail_port: v })} min={1} max={65535} />
        </Field>
      </div>
    </div>
  );
}

function Toast({ msg, type }) {
  if (!msg) return null;
  return (
    <div className={`fixed bottom-4 right-4 z-50 px-4 py-3 rounded-lg shadow-lg text-sm text-white flex items-center gap-2 ${
      type === 'error' ? 'bg-red-600' : 'bg-green-600'
    }`}>
      {type === 'error' ? <XCircle className="h-4 w-4 shrink-0" /> : <CheckCircle className="h-4 w-4 shrink-0" />}
      {msg}
    </div>
  );
}

export default function EmailPage() {
  const { user } = useAuth();
  const isAdmin = user?.role === 'admin';
  const [activeTab, setActiveTab] = useState('overview');
  const { domain = 'cell', effective_domain, domain_mode = 'lan', service_ips = {}, service_configs = {}, refresh: refreshConfig } = useConfig();
  const draftConfig = useDraftConfig();

  const svcDomain = (domain_mode !== 'lan' && effective_domain) ? effective_domain : domain;
  const proto = domain_mode === 'lan' ? 'http' : 'https';
  const cellHost = `mail.${svcDomain}`;
  const mailIp   = service_ips.vip_mail || '172.20.0.23';
  const dnsIp    = service_ips.dns      || '172.20.0.3';
  const emailCfgServer = service_configs.email || {};
  const imapPort    = emailCfgServer.imap_port    ?? 993;
  const smtpPort    = emailCfgServer.smtp_port    ?? 25;
  const webmailPort = emailCfgServer.webmail_port ?? 8888;

  // Admin state
  const [emailCfg, setEmailCfg] = useState({ ...EMAIL_DEFAULTS });
  const [dirty, setDirty]       = useState(false);
  const [saving, setSaving]     = useState(false);
  const [users, setUsers]       = useState([]);
  const [status, setStatus]     = useState(null);
  const [toast, setToast]       = useState(null);

  // Peer state
  const [peerData, setPeerData] = useState(null);

  useEffect(() => {
    if (service_configs.email) setEmailCfg({ ...EMAIL_DEFAULTS, ...service_configs.email });
  }, [service_configs.email]);

  useEffect(() => {
    if (!isAdmin) {
      peerAPI.services().then(r => setPeerData(r.data)).catch(() => {});
      return;
    }
    emailAPI.getUsers().then(r => setUsers(r.data)).catch(() => {});
    emailAPI.getStatus().then(r => setStatus(r.data)).catch(() => {});
  }, [isAdmin]);

  const showToast = (msg, type = 'success') => {
    setToast({ msg, type });
    setTimeout(() => setToast(null), 3000);
  };

  const errors = useMemo(() => validateEmailConfig(emailCfg), [emailCfg]);

  const portConflicts = useMemo(
    () => detectPortConflicts({ ...service_configs, email: emailCfg }),
    [emailCfg, service_configs]
  );

  const hasErrors = useMemo(
    () => Object.keys(errors).length > 0 ||
          PORT_CONFLICT_FIELDS.email.some(f => portConflicts[`email|${f}`]),
    [errors, portConflicts]
  );

  // Refs so flusher closure always sees current values after navigation
  const emailCfgRef = useRef(emailCfg);
  useEffect(() => { emailCfgRef.current = emailCfg; }, [emailCfg]);
  const dirtyRef = useRef(dirty);
  useEffect(() => { dirtyRef.current = dirty; }, [dirty]);
  const hasErrorsRef = useRef(hasErrors);
  useEffect(() => { hasErrorsRef.current = hasErrors; }, [hasErrors]);

  const save = useCallback(async () => {
    if (!dirtyRef.current || hasErrorsRef.current) return;
    setSaving(true);
    try {
      await cellAPI.updateConfig({ email: emailCfgRef.current });
      setDirty(false);
      draftConfig?.setDirty('email', false);
      refreshConfig();
    } catch (err) {
      showToast(err?.response?.data?.error || 'Failed to save email config', 'error');
    } finally {
      setSaving(false);
    }
  }, [draftConfig, refreshConfig]);

  const saveRef = useRef(save);
  useEffect(() => { saveRef.current = save; }, [save]);

  // Register flusher without cleanup so it persists when user navigates away mid-edit
  useEffect(() => {
    if (!draftConfig) return;
    draftConfig.registerFlusher('email', () => saveRef.current());
  }, [draftConfig]); // eslint-disable-line react-hooks/exhaustive-deps

  // Debounced auto-save
  useEffect(() => {
    if (!dirty || hasErrors) return;
    const t = setTimeout(() => saveRef.current(), 800);
    return () => clearTimeout(t);
  }, [emailCfg, dirty, hasErrors]); // eslint-disable-line react-hooks/exhaustive-deps

  const handleChange = (cfg) => {
    setEmailCfg(cfg);
    setDirty(true);
    draftConfig?.setDirty('email', true);
  };

  return (
    <div>
      <Toast {...(toast || {})} />

      <div className="mb-6">
        <h1 className="text-2xl font-bold text-gray-900">Email Services</h1>
        <p className="mt-2 text-gray-600">Postfix (SMTP) + Dovecot (IMAP)</p>
      </div>

      {isAdmin && (
        <div className="mb-6 border-b border-gray-200">
          <nav className="-mb-px flex space-x-6 overflow-x-auto">
            {[{id:'overview',label:'Overview'},{id:'accounts',label:'Accounts'}].map(tab => (
              <button key={tab.id} onClick={() => setActiveTab(tab.id)}
                className={`whitespace-nowrap px-1 py-3 text-sm font-medium border-b-2 transition-colors ${
                  activeTab === tab.id
                    ? 'border-primary-500 text-primary-600'
                    : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
                }`}>
                {tab.label}
              </button>
            ))}
          </nav>
        </div>
      )}

      {activeTab === 'accounts' && isAdmin ? (
        <ServiceAccountsPanel serviceId="email" serviceName="Email" />
      ) : (
      <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
        {/* IMAP */}
        <div className="card">
          <div className="flex items-center mb-4">
            <Wifi className="h-5 w-5 text-primary-500 mr-2" />
            <h3 className="text-lg font-medium text-gray-900">Incoming mail (IMAP)</h3>
          </div>
          <div className="bg-gray-50 rounded-lg px-4 py-2">
            <InfoRow label="Server"    value={cellHost} />
            <InfoRow label="Port"      value={String(imapPort)} />
            <InfoRow label="Security"  value="SSL/TLS" />
            <InfoRow label="Direct IP" value={mailIp} />
          </div>
        </div>

        {/* SMTP */}
        <div className="card">
          <div className="flex items-center mb-4">
            <Mail className="h-5 w-5 text-primary-500 mr-2" />
            <h3 className="text-lg font-medium text-gray-900">Outgoing mail (SMTP)</h3>
          </div>
          <div className="bg-gray-50 rounded-lg px-4 py-2">
            <InfoRow label="Server"    value={cellHost} />
            <InfoRow label="Port"      value={String(smtpPort)} />
            <InfoRow label="Security"  value="STARTTLS" />
            <InfoRow label="Auth"      value="Username + Password" />
          </div>
        </div>

        {/* Webmail */}
        <div className="card">
          <div className="flex items-center mb-4">
            <Mail className="h-5 w-5 text-primary-500 mr-2" />
            <h3 className="text-lg font-medium text-gray-900">Webmail</h3>
          </div>
          <div className="bg-gray-50 rounded-lg px-4 py-2">
            <InfoRow label="URL"         value={`${proto}://mail.${svcDomain}`} />
            <InfoRow label="Alt URL"     value={`${proto}://webmail.${svcDomain}`} />
            <InfoRow label="Direct IP"   value={`http://${mailIp}`} />
            <InfoRow label="Direct port" value={String(webmailPort)} />
          </div>
          <p className="text-xs text-gray-400 mt-3">
            Requires VPN + DNS set to <span className="font-mono">{dnsIp}</span>.
          </p>
        </div>

        {/* Status — admin only */}
        {isAdmin && (
          <div className="card">
            <div className="flex items-center mb-4">
              <Server className="h-6 w-6 text-primary-500 mr-2" />
              <h3 className="text-lg font-medium text-gray-900">Service Status</h3>
            </div>
            {status ? (
              <div className="space-y-2">
                <div className="flex justify-between">
                  <span className="text-sm text-gray-500">Postfix (SMTP):</span>
                  <span className="text-sm font-medium text-success-600">Running</span>
                </div>
                <div className="flex justify-between">
                  <span className="text-sm text-gray-500">Dovecot (IMAP):</span>
                  <span className="text-sm font-medium text-success-600">Running</span>
                </div>
              </div>
            ) : (
              <p className="text-gray-500 text-sm">Status unavailable</p>
            )}
          </div>
        )}

        {/* Peer credentials */}
        {!isAdmin && peerData?.email && (
          <div className="card">
            <div className="flex items-center mb-4">
              <Mail className="h-5 w-5 text-primary-500 mr-2" />
              <h3 className="text-lg font-medium text-gray-900">Your Account</h3>
            </div>
            <div className="bg-gray-50 rounded-lg px-4 py-2">
              <InfoRow label="Email address" value={peerData.email.address || '—'} />
              <InfoRow label="Username"      value={peerData.username || '—'} />
            </div>
            <p className="text-xs text-gray-400 mt-3">Authenticate with your dashboard username and password.</p>
          </div>
        )}

        {/* Admin users list */}
        {isAdmin && users.length > 0 && (
          <div className="card lg:col-span-2">
            <div className="flex items-center mb-4">
              <Users className="h-6 w-6 text-primary-500 mr-2" />
              <h3 className="text-lg font-medium text-gray-900">Email Accounts</h3>
            </div>
            <div className="space-y-2">
              {users.map((u, i) => (
                <div key={i} className="flex justify-between items-center p-2 bg-gray-50 rounded">
                  <span className="text-sm font-medium">{u.username}</span>
                  <span className="text-sm text-gray-500">{u.domain}</span>
                </div>
              ))}
            </div>
          </div>
        )}
      </div>

      </div>
      )}

      {isAdmin && activeTab !== 'accounts' && (
        <AdminConfigSection
          emailCfg={emailCfg}
          onChange={handleChange}
          errors={errors}
          portConflicts={portConflicts}
          saving={saving}
        />
      )}
    </div>
  );
}
