import { useEffect, useState } from "react";
import { Link, Outlet, useLocation, useOutletContext } from "react-router-dom";

import { getUserConfig, updateUserConfig, type UserConfig, type UserConfigUpdate } from "../api/settings";
import { EmptyState, ErrorState, LoadingState } from "../components/data-states";
import { Icon } from "../components/icon";
import { useAsyncData } from "../hooks/use-async-data";

const TABS = [
  { label: "General", path: "general" },
  { label: "SSH Keys", path: "ssh-keys" },
] as const;

const THEME_OPTIONS = [
  { value: "system", label: "System" },
  { value: "light", label: "Light" },
  { value: "dark", label: "Dark" },
];

type SettingsOutletContext = {
  config: UserConfig;
  handleChange: (key: keyof UserConfigUpdate, value: string | null) => void;
  handleSave: () => Promise<void>;
  saveStatus: "idle" | "saving" | "saved" | "error";
};

export const SettingsPage = () => {
  const location = useLocation();
  const { data: loadedConfig, status, reload } = useAsyncData<UserConfig>(getUserConfig, []);
  const [config, setConfig] = useState<UserConfig>({
    theme: "system",
    default_editor: null,
    git_user_name: null,
    git_user_email: null,
    last_session_id: null,
  });
  const [saveStatus, setSaveStatus] = useState<"idle" | "saving" | "saved" | "error">("idle");

  // Sync loaded config into local editable state
  useEffect(() => {
    if (loadedConfig) {
      setConfig(loadedConfig);
    }
  }, [loadedConfig]);

  const handleChange = (key: keyof UserConfigUpdate, value: string | null) => {
    setConfig((prev) => ({ ...prev, [key]: value }));
    setSaveStatus("idle");
  };

  const handleSave = async () => {
    setSaveStatus("saving");
    try {
      const update: UserConfigUpdate = {
        theme: config.theme,
        default_editor: config.default_editor,
        git_user_name: config.git_user_name,
        git_user_email: config.git_user_email,
      };
      const updated = await updateUserConfig(update);
      setConfig(updated);
      setSaveStatus("saved");
      if (updated.theme === "system") {
        document.documentElement.removeAttribute("data-theme");
      } else {
        document.documentElement.setAttribute("data-theme", updated.theme);
      }
      window.setTimeout(() => setSaveStatus("idle"), 2000);
    } catch {
      setSaveStatus("error");
    }
  };

  if (status === "loading") {
    return <section className="stack"><LoadingState message="Loading settings..." /></section>;
  }

  if (status === "error") {
    return (
      <section className="stack">
        <ErrorState message="Failed to load settings" onRetry={reload} />
      </section>
    );
  }

  const parts = location.pathname.split("/").filter(Boolean);
  const activePath = location.pathname.endsWith("/settings") ? "general" : (parts[parts.length - 1] ?? "general");

  return (
    <section className="stack settings-page">
      <header className="settings-header card stack-sm">
        <div>
          <p className="eyebrow">Configuration</p>
          <h1>Settings</h1>
        </div>
        <p className="muted">General preferences, SSH keys, and config profiles.</p>
      </header>

      <nav className="settings-tabs" aria-label="Settings sections">
        {TABS.map((tab) => (
          <Link
            key={tab.path}
            className={`settings-tab ${activePath === tab.path ? "active" : ""}`}
            to={tab.path === "general" ? "/settings" : `/settings/${tab.path}`}
          >
            {tab.label}
          </Link>
        ))}
      </nav>

      <div className="settings-panel card">
        <Outlet context={{ config, handleChange, handleSave, saveStatus }} />
      </div>
    </section>
  );
};

export const GeneralSettingsTab = () => {
  const { config, handleChange, handleSave, saveStatus } = useOutletContext<SettingsOutletContext>();

  return (
    <div className="stack">
      <h2>General</h2>
      <label className="form-field">
        Theme
        <select value={config.theme} onChange={(e) => handleChange("theme", e.target.value)}>
          {THEME_OPTIONS.map((opt) => (
            <option key={opt.value} value={opt.value}>{opt.label}</option>
          ))}
        </select>
      </label>
      <label className="form-field">
        Git user name
        <input type="text" value={config.git_user_name ?? ""} onChange={(e) => handleChange("git_user_name", e.target.value || null)} placeholder="Your git commit name" />
      </label>
      <label className="form-field">
        Git user email
        <input type="email" value={config.git_user_email ?? ""} onChange={(e) => handleChange("git_user_email", e.target.value || null)} placeholder="your.email@example.com" />
      </label>
      <label className="form-field">
        Default editor
        <input type="text" value={config.default_editor ?? ""} onChange={(e) => handleChange("default_editor", e.target.value || null)} placeholder="e.g., vscode, vim, cursor" />
      </label>
      <div className="settings-actions">
        <button className="primary-button" onClick={() => void handleSave()} type="button">
          {saveStatus === "saving" ? <><Icon name="loading" size="sm" /> Saving...</> : <><Icon name="save" size="sm" /> Save Settings</>}
        </button>
        {saveStatus === "saved" && <span className="success-text">Settings saved!</span>}
        {saveStatus === "error" && <span className="error-text">Failed to save</span>}
      </div>
    </div>
  );
};
