import { useCallback, useEffect, useMemo, useRef, useState, type FormEvent } from "react";
import {
  AndroidLogo,
  ArrowClockwise,
  MagnifyingGlass,
  Package,
  Play,
  Plus,
  Trash,
  UploadSimple,
  WarningCircle
} from "@phosphor-icons/react";
import {
  deleteAdbShortcut,
  getAdbPackages,
  getAdbShortcuts,
  post,
  uploadApk,
  type AdbShortcut,
  type AdbTarget,
  type InstalledAdbPackage
} from "./api";

const suggestions = [
  { name: "Developer options", value: "com.android.settings/.Settings$DevelopmentSettingsDashboardActivity" },
  { name: "System settings", value: "com.saicmotor.hmi.systemsettings/.SettingsActivity" },
  { name: "Engineering mode", value: "com.saicmotor.hmi.engmode/.home.ui.EngineeringModeActivity" }
] as const;

export function AdbPage({ csrfToken }: { csrfToken: string }) {
  const fileInput = useRef<HTMLInputElement>(null);
  const [packages, setPackages] = useState<InstalledAdbPackage[]>([]);
  const [shortcuts, setShortcuts] = useState<AdbShortcut[]>([]);
  const [query, setQuery] = useState("");
  const [name, setName] = useState("");
  const [target, setTarget] = useState("");
  const [targetType, setTargetType] = useState<AdbTarget["type"]>("component");
  const [loading, setLoading] = useState(true);
  const [busy, setBusy] = useState("");
  const [message, setMessage] = useState("");
  const [error, setError] = useState("");

  const refresh = useCallback(async () => {
    setLoading(true);
    const [packageResult, shortcutResult] = await Promise.allSettled([getAdbPackages(), getAdbShortcuts()]);
    if (packageResult.status === "fulfilled") setPackages(packageResult.value);
    if (shortcutResult.status === "fulfilled") setShortcuts(shortcutResult.value);
    const failure = packageResult.status === "rejected" ? packageResult.reason : shortcutResult.status === "rejected" ? shortcutResult.reason : null;
    setError(failure instanceof Error ? failure.message : failure ? "ADB data could not be loaded" : "");
    setLoading(false);
  }, []);

  useEffect(() => { void refresh(); }, [refresh]);

  const visiblePackages = useMemo(() => {
    const normalized = query.trim().toLowerCase();
    return normalized ? packages.filter((item) => item.packageName.toLowerCase().includes(normalized)) : packages;
  }, [packages, query]);

  async function install(file: File | undefined) {
    if (!file) return;
    if (!file.name.toLowerCase().endsWith(".apk")) {
      setError("Choose a file ending in .apk");
      return;
    }
    setBusy("install");
    setMessage("");
    setError("");
    try {
      await uploadApk(file, csrfToken);
      setMessage(`${file.name} was installed`);
      await refresh();
    } catch (caught) {
      setError(caught instanceof Error ? caught.message : "The APK could not be installed");
    } finally {
      setBusy("");
      if (fileInput.current) fileInput.current.value = "";
    }
  }

  async function launch(nextTarget: AdbTarget, busyKey: string) {
    setBusy(busyKey);
    setMessage("");
    setError("");
    try {
      await post("/api/adb/launch", nextTarget, csrfToken);
      setMessage("Opened on the infotainment screen");
    } catch (caught) {
      setError(caught instanceof Error ? caught.message : "The target could not be opened");
    } finally {
      setBusy("");
    }
  }

  async function saveShortcut(event: FormEvent) {
    event.preventDefault();
    setBusy("save");
    setMessage("");
    setError("");
    try {
      const shortcut = await post<AdbShortcut>("/api/adb/shortcuts", { name, type: targetType, value: target }, csrfToken);
      setShortcuts((current) => [...current, shortcut]);
      setName("");
      setTarget("");
      setMessage("Shortcut saved");
    } catch (caught) {
      setError(caught instanceof Error ? caught.message : "The shortcut could not be saved");
    } finally {
      setBusy("");
    }
  }

  async function removeShortcut(id: number) {
    setBusy(`delete-${id}`);
    try {
      await deleteAdbShortcut(id, csrfToken);
      setShortcuts((current) => current.filter((item) => item.id !== id));
      setMessage("Shortcut removed");
      setError("");
    } catch (caught) {
      setError(caught instanceof Error ? caught.message : "The shortcut could not be removed");
    } finally {
      setBusy("");
    }
  }

  return (
    <div className="adb-page">
      {(error || message) && <div className={error ? "status-error" : "adb-success"} role="status">
        {error ? <WarningCircle size={21} /> : <AndroidLogo size={21} />}{error || message}
      </div>}

      <section className="adb-command-grid">
        <div className="adb-install-panel">
          <div className="panel-heading"><div><h2>Install an APK</h2><p>Upload and replace an app directly on the connected head unit.</p></div><UploadSimple size={30} /></div>
          <input ref={fileInput} className="visually-hidden" type="file" accept=".apk,application/vnd.android.package-archive" onChange={(event) => void install(event.target.files?.[0])} />
          <button className="primary-button" onClick={() => fileInput.current?.click()} disabled={Boolean(busy)}>
            <UploadSimple size={21} />{busy === "install" ? "Installing..." : "Choose APK"}
          </button>
          <small>Maximum file size: 256 MB. Existing apps are updated in place.</small>
        </div>

        <form className="shortcut-form" onSubmit={(event) => void saveShortcut(event)}>
          <div className="panel-heading"><div><h2>Save a shortcut</h2><p>Use a package name or an explicit Android activity.</p></div><Plus size={28} /></div>
          <div className="shortcut-fields">
            <label><span>Name</span><input value={name} onChange={(event) => setName(event.target.value)} placeholder="Developer options" required maxLength={48} /></label>
            <label><span>Target type</span><select value={targetType} onChange={(event) => setTargetType(event.target.value as AdbTarget["type"])}><option value="component">Activity</option><option value="package">App package</option></select></label>
            <label className="target-field"><span>{targetType === "component" ? "Package/activity" : "Package name"}</span><input value={target} onChange={(event) => setTarget(event.target.value)} placeholder={targetType === "component" ? "com.example/.MainActivity" : "com.example.app"} required maxLength={240} /></label>
          </div>
          <div className="shortcut-form-footer">
            <div className="suggestion-list" aria-label="Suggested targets">
              {suggestions.map((item) => <button type="button" key={item.name} onClick={() => { setName(item.name); setTargetType("component"); setTarget(item.value); }}>{item.name}</button>)}
            </div>
            <button className="secondary-button" type="submit" disabled={Boolean(busy)}><Plus size={20} />{busy === "save" ? "Saving..." : "Save"}</button>
          </div>
        </form>
      </section>

      {shortcuts.length > 0 && <section className="shortcut-strip" aria-label="Saved shortcuts">
        {shortcuts.map((shortcut) => <article key={shortcut.id}>
          <button className="shortcut-launch" onClick={() => void launch(shortcut, `shortcut-${shortcut.id}`)} disabled={Boolean(busy)}>
            <Play size={20} weight="fill" /><span><strong>{shortcut.name}</strong><small>{shortcut.value}</small></span>
          </button>
          <button className="icon-button" aria-label={`Remove ${shortcut.name}`} onClick={() => void removeShortcut(shortcut.id)} disabled={Boolean(busy)}><Trash size={19} /></button>
        </article>)}
      </section>}

      <section className="packages-panel">
        <div className="packages-toolbar">
          <div><h2>Installed apps</h2><p>{loading ? "Reading package manager..." : `${packages.length} packages found`}</p></div>
          <label className="package-search"><MagnifyingGlass size={20} /><span className="visually-hidden">Filter installed apps</span><input value={query} onChange={(event) => setQuery(event.target.value)} placeholder="Filter packages" /></label>
          <button className="icon-button" aria-label="Refresh installed apps" onClick={() => void refresh()} disabled={loading}><ArrowClockwise size={21} className={loading ? "spin" : ""} /></button>
        </div>
        <div className="package-list">
          {!loading && visiblePackages.length === 0 && <div className="adb-empty">No installed packages match this filter.</div>}
          {visiblePackages.map((item) => <article key={item.packageName}>
            <Package size={22} />
            <div><strong>{item.packageName}</strong><small>{item.apkPath}</small></div>
            <span className="package-kind">{item.system ? "System" : "User"}</span>
            <button className="icon-button" aria-label={`Launch ${item.packageName}`} title="Launch app" onClick={() => void launch({ type: "package", value: item.packageName }, `package-${item.packageName}`)} disabled={Boolean(busy)}><Play size={18} weight="fill" /></button>
          </article>)}
        </div>
      </section>
    </div>
  );
}
