import { useEffect, useMemo, useRef, useState } from 'react';
import toast from 'react-hot-toast';
import {
  Bell,
  BriefcaseBusiness,
  Building2,
  Check,
  ChevronLeft,
  Database,
  ListChecks,
  Mail,
  Plus,
  Save,
  Search,
  Settings as SettingsIcon,
  ShieldCheck,
  SlidersHorizontal,
  Trash2,
  Users,
  X,
  CalendarDays,
  TimerReset,
  MessagesSquare,
} from 'lucide-react';
import api from '../services/api';
import ThemeAccentPicker from '../components/ThemeAccentPicker';
import { applyThemeMode, getThemeMode, themeModes } from '../utils/themeMode';

const groupMeta = {
  general: { label: 'عمومی', icon: Building2 },
  task: { label: 'تسک‌ها', icon: ListChecks },
  project: { label: 'پروژه‌ها', icon: BriefcaseBusiness },
  backlog: { label: 'بک‌لاگ', icon: Database },
  notification: { label: 'اعلان‌ها', icon: Bell },
  mail: { label: 'ایمیل', icon: Mail },
  security: { label: 'امنیت', icon: ShieldCheck },
  app: { label: 'برنامه', icon: SlidersHorizontal },
  people: { label: 'منابع انسانی', icon: Users },
  personalization: { label: 'شخصی‌سازی', icon: SlidersHorizontal },
  calendar: { label: 'تقویم و زمان کاری', icon: CalendarDays },
  sprint: { label: 'Sprint و Agile', icon: TimerReset },
  meeting: { label: 'جلسات و یادآوری', icon: MessagesSquare },
};

const groupDescriptions = {
  general: 'هویت، اطلاعات تماس و تنظیمات عمومی سازمان',
  personalization: 'ظاهر سامانه، حالت نمایش و رنگ‌بندی شخصی',
  notification: 'نوع‌ها، کانال‌ها و سیاست دریافت اعلان',
  calendar: 'منطقه زمانی، روزهای کاری و رفتار تقویم',
  sprint: 'قواعد سلامت Sprint و سیاست‌های Agile',
  meeting: 'پیش‌فرض جلسه، یادآوری و ارزیابی اثربخشی',
  security: 'کنترل‌های امنیتی و سیاست‌های دسترسی',
  mail: 'ارسال ایمیل و زیرساخت SMTP',
};

const typeLabels = {
  string: 'متن کوتاه',
  textarea: 'متن بلند',
  number: 'عدد',
  boolean: 'کلید روشن/خاموش',
  list: 'لیست',
  json: 'ساختار داده',
};

const keyLabels = {
  company_name: 'نام شرکت',
  company_phone: 'شماره تماس شرکت',
  company_address: 'آدرس شرکت',
  company_logo: 'مسیر لوگوی شرکت',
  default_task_statuses: 'وضعیت‌های پیش‌فرض تسک',
  default_priorities: 'اولویت‌های پیش‌فرض',
  default_project_statuses: 'وضعیت‌های پیش‌فرض پروژه',
  risk_levels: 'سطوح ریسک',
  backlog_types: 'نوع‌های بک‌لاگ',
  backlog_statuses: 'وضعیت‌های بک‌لاگ',
  notification_types: 'نوع‌های اعلان',
  smtp_settings: 'تنظیمات SMTP',
  job_titles: 'عنوان‌های شغلی',
  working_days: 'روزهای کاری سازمان',
  organization_timezone: 'منطقه زمانی سازمان',
  default_meeting_reminder_minutes: 'یادآوری پیش‌فرض جلسه',
  meeting_effectiveness_enabled: 'ارزیابی اثربخشی جلسه',
  sprint_health_override_requires_reason: 'الزام دلیل برای تغییر سلامت Sprint',
};

const emptySetting = {
  key: '',
  value: '',
  group: 'general',
  type: 'string',
};

const isPlainObject = (value) => value && typeof value === 'object' && !Array.isArray(value);

const inferType = (setting) => {
  if (setting.type) return setting.type;
  if (Array.isArray(setting.value)) return 'list';
  if (isPlainObject(setting.value)) return 'json';
  if (typeof setting.value === 'boolean') return 'boolean';
  if (typeof setting.value === 'number') return 'number';
  if (typeof setting.value === 'string' && setting.value.length > 90) return 'textarea';
  return 'string';
};

const getGroupLabel = (group) => groupMeta[group]?.label || group || 'عمومی';
const getKeyLabel = (key) => keyLabels[key] || key.replaceAll('_', ' ');

const toDraft = (setting) => ({
  value: setting.value ?? '',
  group: setting.group || 'general',
  type: inferType(setting),
});

const normalizeByType = (type, value) => {
  if (type === 'boolean') return value === true || value === 'true';
  if (type === 'number') return value === '' || value === null ? null : Number(value);
  if (type === 'list') return Array.isArray(value) ? value.map(String).filter((item) => item.trim()) : String(value || '').split('\n').map((item) => item.trim()).filter(Boolean);
  if (type === 'json') return isPlainObject(value) ? value : {};
  return value ?? '';
};

const createPayload = (form) => ({
  ...form,
  value: normalizeByType(form.type, form.value),
});

export default function Settings() {
  const [settings, setSettings] = useState([]);
  const [drafts, setDrafts] = useState({});
  const [loading, setLoading] = useState(true);
  const [activeGroup, setActiveGroup] = useState('');
  const [search, setSearch] = useState('');
  const [savingId, setSavingId] = useState(null);
  const [addOpen, setAddOpen] = useState(false);
  const [addForm, setAddForm] = useState(emptySetting);
  const [adding, setAdding] = useState(false);

  const fetchSettings = async () => {
    setLoading(true);
    try {
      const { data } = await api.get('/settings');
      const nextSettings = data.data || [];
      setSettings(nextSettings);
      setDrafts(Object.fromEntries(nextSettings.map((setting) => [setting.id, toDraft(setting)])));
      setActiveGroup((current) => current || nextSettings[0]?.group || 'personalization');
    } catch {
      toast.error('خطا در دریافت تنظیمات');
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => { fetchSettings(); }, []);

  const groups = useMemo(() => {
    const counts = settings.reduce((acc, setting) => {
      const group = setting.group || 'general';
      acc[group] = (acc[group] || 0) + 1;
      return acc;
    }, {});
    return Object.entries(counts).map(([key, count]) => ({ key, count }));
  }, [settings]);

  const visibleSettings = useMemo(() => {
    const q = search.trim().toLowerCase();
    return settings.filter((setting) => {
      const group = setting.group || 'general';
      const draft = drafts[setting.id] || toDraft(setting);
      const key = setting.key || '';
      const label = getKeyLabel(key);
      const valueText = typeof draft.value === 'string' ? draft.value : JSON.stringify(draft.value || '');
      const matchesGroup = group === activeGroup;
      const matchesSearch = !q || key.toLowerCase().includes(q) || label.toLowerCase().includes(q) || valueText.toLowerCase().includes(q);
      return matchesGroup && matchesSearch;
    });
  }, [settings, drafts, activeGroup, search]);

  const summary = useMemo(() => ({
    total: settings.length,
    groups: groups.length,
    structured: settings.filter((setting) => ['list', 'json'].includes(inferType(setting))).length,
    missingType: settings.filter((setting) => !setting.type).length,
  }), [settings, groups.length]);

  const dirtySettings = useMemo(() => settings.filter((setting) => {
    const original = toDraft(setting);
    const draft = drafts[setting.id] || original;
    return JSON.stringify({
      value: normalizeByType(draft.type, draft.value),
      group: draft.group,
      type: draft.type,
    }) !== JSON.stringify({
      value: normalizeByType(original.type, original.value),
      group: original.group,
      type: original.type,
    });
  }), [settings, drafts]);

  useEffect(() => {
    const warnUnsaved = (event) => {
      if (dirtySettings.length === 0) return;
      event.preventDefault();
      event.returnValue = '';
    };
    window.addEventListener('beforeunload', warnUnsaved);
    return () => window.removeEventListener('beforeunload', warnUnsaved);
  }, [dirtySettings.length]);

  const updateDraft = (id, patch) => {
    setDrafts((prev) => ({ ...prev, [id]: { ...prev[id], ...patch } }));
  };

  const resetSetting = (setting) => {
    updateDraft(setting.id, toDraft(setting));
  };

  const saveSetting = async (setting) => {
    const draft = drafts[setting.id] || toDraft(setting);
    const payload = {
      value: normalizeByType(draft.type, draft.value),
      group: draft.group,
      type: draft.type,
    };
    if (draft.type === 'number' && Number.isNaN(payload.value)) {
      toast.error('مقدار عددی معتبر نیست');
      return;
    }
    setSavingId(setting.id);
    try {
      const { data } = await api.put(`/settings/${setting.id}`, payload);
      const updated = data.data;
      setSettings((prev) => prev.map((item) => (item.id === setting.id ? updated : item)));
      setDrafts((prev) => ({ ...prev, [setting.id]: toDraft(updated) }));
      toast.success('تنظیم ذخیره شد');
    } catch (err) {
      toast.error(err.response?.data?.message || 'خطا در ذخیره تنظیم');
    } finally {
      setSavingId(null);
    }
  };

  const addSetting = async (e) => {
    e.preventDefault();
    if (!addForm.key.trim()) {
      toast.error('کلید تنظیم الزامی است');
      return;
    }
    setAdding(true);
    try {
      const { data } = await api.post('/settings', createPayload(addForm));
      const created = data.data;
      setSettings((prev) => [...prev, created]);
      setDrafts((prev) => ({ ...prev, [created.id]: toDraft(created) }));
      setActiveGroup(created.group || 'general');
      setAddOpen(false);
      setAddForm(emptySetting);
      toast.success('تنظیم جدید ایجاد شد');
    } catch (err) {
      const firstError = Object.values(err.response?.data?.errors || {})[0]?.[0];
      toast.error(firstError || err.response?.data?.message || 'خطا در ایجاد تنظیم');
    } finally {
      setAdding(false);
    }
  };

  const saveAll = async () => {
    if (dirtySettings.length === 0) return;
    setSavingId('all');
    try {
      await Promise.all(dirtySettings.map((setting) => {
        const draft = drafts[setting.id] || toDraft(setting);
        return api.put(`/settings/${setting.id}`, {
          value: normalizeByType(draft.type, draft.value),
          group: draft.group,
          type: draft.type,
        });
      }));
      await fetchSettings();
      toast.success(`${dirtySettings.length} تنظیم ذخیره شد`);
    } catch (err) {
      toast.error(err.response?.data?.message || 'ذخیره گروهی تنظیمات ناموفق بود');
    } finally {
      setSavingId(null);
    }
  };

  const activeGroupTitle = activeGroup === 'personalization' ? 'شخصی‌سازی' : getGroupLabel(activeGroup);

  return (
    <div className="page-container settings-page">
      <div className="page-header settings-header">
        <div>
          <h1>مرکز تنظیمات</h1>
          <p className="settings-subtitle">تنظیمات شخصی و سیاست‌های سازمان را از یک نقطه مدیریت کنید.</p>
        </div>
        <button className="btn btn-primary" onClick={() => setAddOpen(true)}>
          <Plus size={16} />
          تنظیم جدید
        </button>
      </div>

      <div className="settings-summary">
        <SummaryItem label="کل تنظیمات" value={summary.total} icon={SettingsIcon} />
        <SummaryItem label="گروه‌ها" value={summary.groups} icon={Database} />
        <SummaryItem label="ساختاری" value={summary.structured} icon={ListChecks} />
        <SummaryItem label="بدون نوع ثبت‌شده" value={summary.missingType} icon={ShieldCheck} />
      </div>

      <div className="settings-shell">
        <aside className="settings-nav">
          <button className={`settings-nav-item ${activeGroup === 'personalization' ? 'active' : ''}`} onClick={() => setActiveGroup('personalization')}>
            <span><SlidersHorizontal size={16} /> شخصی‌سازی</span>
          </button>
          {groups.map(({ key }) => {
            const Icon = groupMeta[key]?.icon || SlidersHorizontal;
            return (
              <button key={key} className={`settings-nav-item ${activeGroup === key ? 'active' : ''}`} onClick={() => setActiveGroup(key)}>
                <span><Icon size={16} /> {getGroupLabel(key)}</span>
              </button>
            );
          })}
        </aside>

        <main className="settings-main">
          <div className="settings-toolbar">
            <div>
              <h2>{activeGroupTitle}</h2>
              <span>{groupDescriptions[activeGroup] || `${visibleSettings.length} مورد`}</span>
            </div>
            <div className="settings-search">
              <Search size={16} />
              <input className="form-input" value={search} onChange={(e) => setSearch(e.target.value)} placeholder="جستجو در کلید، عنوان یا مقدار" />
            </div>
          </div>

          {activeGroup === 'personalization' ? (
            <AppearancePanel />
          ) : loading ? (
            <div className="settings-list">
              {[1, 2, 3, 4].map((item) => <div key={item} className="skeleton settings-skeleton" />)}
            </div>
          ) : visibleSettings.length === 0 ? (
            <div className="settings-empty">
              <SettingsIcon size={34} />
              <strong>تنظیمی یافت نشد</strong>
              <span>فیلتر یا عبارت جستجو را تغییر دهید.</span>
            </div>
          ) : (
            <div className="settings-list">
              {visibleSettings.map((setting) => (
                <SettingRow
                  key={setting.id}
                  setting={setting}
                  draft={drafts[setting.id] || toDraft(setting)}
                  saving={savingId === setting.id}
                  onChange={(patch) => updateDraft(setting.id, patch)}
                  onReset={() => resetSetting(setting)}
                  onSave={() => saveSetting(setting)}
                />
              ))}
            </div>
          )}
        </main>
      </div>

      {dirtySettings.length > 0 && (
        <div className="settings-unsaved-bar" role="status">
          <div><strong>{dirtySettings.length} تغییر ذخیره‌نشده</strong><span>تغییرات تا زمان ذخیره روی سازمان اعمال نمی‌شوند.</span></div>
          <div><button type="button" className="btn btn-secondary" onClick={() => setDrafts(Object.fromEntries(settings.map((setting) => [setting.id, toDraft(setting)])))}>لغو تغییرات</button><button type="button" className="btn btn-primary" onClick={saveAll} disabled={savingId === 'all'}><Save size={16} /> {savingId === 'all' ? 'در حال ذخیره...' : 'ذخیره همه'}</button></div>
        </div>
      )}

      {addOpen && <div className="drawer-overlay" onClick={() => setAddOpen(false)} />}
      {addOpen && (
        <div className="drawer settings-drawer">
          <div className="drawer-header">
            <h3 className="drawer-title">تنظیم جدید</h3>
            <button className="modal-close" onClick={() => setAddOpen(false)}><X size={18} /></button>
          </div>
          <form className="drawer-body settings-add-form" onSubmit={addSetting}>
            <Field label="کلید">
              <input className="form-input" value={addForm.key} onChange={(e) => setAddForm({ ...addForm, key: e.target.value })} placeholder="example_setting_key" />
            </Field>
            <div className="grid grid-2">
              <Field label="گروه">
                <input className="form-input" value={addForm.group} onChange={(e) => setAddForm({ ...addForm, group: e.target.value })} list="settings-groups" />
                <datalist id="settings-groups">
                  {Object.keys(groupMeta).map((group) => <option key={group} value={group} />)}
                  {groups.map(({ key }) => <option key={key} value={key} />)}
                </datalist>
              </Field>
              <Field label="نوع">
                <select className="form-select" value={addForm.type} onChange={(e) => setAddForm({ ...addForm, type: e.target.value, value: e.target.value === 'list' ? [] : e.target.value === 'json' ? {} : '' })}>
                  {Object.entries(typeLabels).map(([key, label]) => <option key={key} value={key}>{label}</option>)}
                </select>
              </Field>
            </div>
            <Field label="مقدار">
              <AddValueEditor form={addForm} onChange={(value) => setAddForm({ ...addForm, value })} />
            </Field>
            <div className="drawer-footer">
              <button type="button" className="btn btn-secondary" onClick={() => setAddOpen(false)}>انصراف</button>
              <button type="submit" className="btn btn-primary" disabled={adding}>
                <Save size={16} />
                {adding ? 'در حال ذخیره...' : 'ذخیره'}
              </button>
            </div>
          </form>
        </div>
      )}
    </div>
  );
}

function AppearancePanel() {
  const [mode, setMode] = useState(getThemeMode);

  useEffect(() => {
    applyThemeMode(mode);
  }, [mode]);

  return (
    <section className="settings-appearance-panel">
      <div>
        <strong>ظاهر سامانه</strong>
      </div>
      <div className="settings-appearance-controls">
        <label>
          <span>حالت نمایش</span>
          <select className="form-select" value={mode} onChange={(e) => setMode(e.target.value)}>
            {themeModes.map((item) => <option key={item.key} value={item.key}>{item.label}</option>)}
          </select>
        </label>
        <ThemeAccentPicker label="رنگ‌بندی" />
      </div>
    </section>
  );
}

function SummaryItem({ label, value, icon: Icon }) {
  return (
    <div className="settings-stat">
      <Icon size={18} />
      <span>{label}</span>
      <strong>{value}</strong>
    </div>
  );
}

function SettingRow({ setting, draft, saving, onChange, onReset, onSave }) {
  const originalType = inferType(setting);
  const hasChanged = JSON.stringify({
    value: normalizeByType(draft.type, draft.value),
    group: draft.group,
    type: draft.type,
  }) !== JSON.stringify({
    value: normalizeByType(originalType, setting.value ?? ''),
    group: setting.group || 'general',
    type: originalType,
  });

  return (
    <section className="settings-item">
      <div className="settings-item-head">
        <div className="settings-item-title">
          <strong>{getKeyLabel(setting.key)}</strong>
          <span>{setting.key}</span>
        </div>
        <div className="settings-item-meta">
          <span className="badge badge-gray">{getGroupLabel(draft.group)}</span>
          <span className="badge badge-info">{typeLabels[draft.type] || draft.type}</span>
        </div>
      </div>

      <div className="settings-editor-grid">
        <div className="settings-editor">
          <ValueEditor type={draft.type} value={draft.value} onChange={(value) => onChange({ value })} />
        </div>
        <div className="settings-side-fields">
          <Field label="گروه">
            <input className="form-input" value={draft.group} onChange={(e) => onChange({ group: e.target.value })} />
          </Field>
          <Field label="نوع مقدار">
            <select className="form-select" value={draft.type} onChange={(e) => onChange({ type: e.target.value, value: normalizeByType(e.target.value, draft.value) })}>
              {Object.entries(typeLabels).map(([key, label]) => <option key={key} value={key}>{label}</option>)}
            </select>
          </Field>
        </div>
      </div>

      <div className="settings-actions">
        <button className="btn btn-secondary btn-sm" onClick={onReset} disabled={!hasChanged}>بازنشانی</button>
        <button className="btn btn-primary btn-sm" onClick={onSave} disabled={!hasChanged || saving}>
          {saving ? <Check size={15} /> : <Save size={15} />}
          {saving ? 'در حال ذخیره...' : 'ذخیره تغییرات'}
        </button>
      </div>
    </section>
  );
}

function ValueEditor({ type, value, onChange }) {
  if (type === 'boolean') {
    const checked = value === true || value === 'true';
    return (
      <div className="settings-toggle" role="group">
        <button className={checked ? 'active' : ''} onClick={() => onChange(true)} type="button">فعال</button>
        <button className={!checked ? 'active' : ''} onClick={() => onChange(false)} type="button">غیرفعال</button>
      </div>
    );
  }

  if (type === 'number') {
    return <input className="form-input" type="number" value={value ?? ''} onChange={(e) => onChange(e.target.value)} />;
  }

  if (type === 'textarea') {
    return <textarea className="form-textarea settings-textarea" value={value ?? ''} onChange={(e) => onChange(e.target.value)} />;
  }

  if (type === 'list') {
    const items = Array.isArray(value) ? value : [];
    return <ListEditor items={items} onChange={onChange} />;
  }

  if (type === 'json') {
    const objectValue = isPlainObject(value) ? value : {};
    return <ObjectEditor value={objectValue} onChange={onChange} />;
  }

  return <input className="form-input" value={value ?? ''} onChange={(e) => onChange(e.target.value)} />;
}

function AddValueEditor({ form, onChange }) {
  if (form.type === 'list') return <ListEditor items={Array.isArray(form.value) ? form.value : []} onChange={onChange} />;
  if (form.type === 'json') return <ObjectEditor value={isPlainObject(form.value) ? form.value : {}} onChange={onChange} />;
  return <ValueEditor type={form.type} value={form.value} onChange={onChange} />;
}

function ListEditor({ items, onChange }) {
  const rowIds = useRef([]);
  const nextRowId = useRef(1);

  if (rowIds.current.length < items.length) {
    rowIds.current = [
      ...rowIds.current,
      ...Array.from({ length: items.length - rowIds.current.length }, () => nextRowId.current++),
    ];
  } else if (rowIds.current.length > items.length) {
    rowIds.current = rowIds.current.slice(0, items.length);
  }

  const updateItem = (index, value) => {
    onChange(items.map((item, itemIndex) => (itemIndex === index ? value : item)));
  };
  const removeItem = (index) => {
    rowIds.current = rowIds.current.filter((_, itemIndex) => itemIndex !== index);
    onChange(items.filter((_, itemIndex) => itemIndex !== index));
  };
  const addItem = () => {
    rowIds.current = [...rowIds.current, nextRowId.current++];
    onChange([...items, '']);
  };

  return (
    <div className="settings-list-editor">
      {items.map((item, index) => (
        <div className="settings-list-row" key={rowIds.current[index]}>
          <input className="form-input" value={item} onChange={(e) => updateItem(index, e.target.value)} />
          <button type="button" className="settings-icon-btn danger" onClick={() => removeItem(index)} title="حذف">
            <Trash2 size={15} />
          </button>
        </div>
      ))}
      <button type="button" className="settings-add-row" onClick={addItem}>
        <Plus size={15} />
        افزودن مورد
      </button>
    </div>
  );
}

function ObjectEditor({ value, onChange }) {
  const rows = Object.entries(value);
  const updateKey = (oldKey, nextKey) => {
    if (!nextKey.trim()) return;
    const next = {};
    rows.forEach(([key, val]) => {
      next[key === oldKey ? nextKey : key] = val;
    });
    onChange(next);
  };
  const updateValue = (key, nextValue) => {
    onChange({ ...value, [key]: nextValue });
  };
  const removeKey = (key) => {
    const next = { ...value };
    delete next[key];
    onChange(next);
  };
  const addKey = () => {
    let index = rows.length + 1;
    let key = `field_${index}`;
    while (Object.prototype.hasOwnProperty.call(value, key)) {
      index += 1;
      key = `field_${index}`;
    }
    onChange({ ...value, [key]: '' });
  };

  return (
    <div className="settings-object-editor">
      {rows.map(([key, val]) => (
        <div className="settings-object-row" key={key}>
          <input className="form-input" value={key} onChange={(e) => updateKey(key, e.target.value)} />
          <ChevronLeft size={15} />
          <input className="form-input" value={val ?? ''} onChange={(e) => updateValue(key, e.target.value)} />
          <button type="button" className="settings-icon-btn danger" onClick={() => removeKey(key)} title="حذف">
            <Trash2 size={15} />
          </button>
        </div>
      ))}
      <button type="button" className="settings-add-row" onClick={addKey}>
        <Plus size={15} />
        افزودن فیلد
      </button>
    </div>
  );
}

function Field({ label, children }) {
  return (
    <div className="form-group">
      <label className="form-label">{label}</label>
      {children}
    </div>
  );
}
