import { computed, onMounted, ref, watch } from "vue";
import { invoke } from "@tauri-apps/api/core";
import { open } from "@tauri-apps/plugin-dialog";

import { sortBookmarks, sortExtensions, sortProfiles } from "../utils/sort";
import type {
  ActiveSection,
  AppPage,
  AssociatedProfileSummary,
  BookmarkAssociatedProfileSummary,
  BookmarkSortKey,
  BrowserConfigEntry,
  BrowserConfigListResponse,
  BrowserView,
  CreateCustomBrowserConfigInput,
  ExtensionSortKey,
  ProfileSortKey,
  ScanResponse,
} from "../types/browser";

export function useBrowserManager() {
  const page = ref<AppPage>("browserData");
  const loading = ref(true);
  const error = ref("");
  const openProfileError = ref("");
  const openingProfileKey = ref("");
  const response = ref<ScanResponse>({ browsers: [] });
  const browserConfigs = ref<BrowserConfigEntry[]>([]);
  const configsLoading = ref(true);
  const configError = ref("");
  const savingConfig = ref(false);
  const deletingConfigId = ref("");
  const createConfigForm = ref<CreateCustomBrowserConfigInput>({
    name: "",
    iconKey: "chrome",
    executablePath: "",
    userDataPath: "",
  });
  const selectedBrowserId = ref("");
  const activeSection = ref<ActiveSection>("profiles");
  const associatedProfilesModal = ref<{
    title: string;
    browserId: string;
    profiles: (AssociatedProfileSummary | BookmarkAssociatedProfileSummary)[];
    isBookmark: boolean;
  } | null>(null);
  const profileSortKey = ref<ProfileSortKey>("name");
  const extensionSortKey = ref<ExtensionSortKey>("name");
  const bookmarkSortKey = ref<BookmarkSortKey>("title");

  const browsers = computed(() => response.value.browsers);
  const currentBrowser = computed<BrowserView | null>(
    () =>
      browsers.value.find((browser) => browser.browserId === selectedBrowserId.value) ??
      browsers.value[0] ??
      null,
  );

  const sortedProfiles = computed(() =>
    sortProfiles(currentBrowser.value?.profiles ?? [], profileSortKey.value),
  );
  const sortedExtensions = computed(() =>
    sortExtensions(currentBrowser.value?.extensions ?? [], extensionSortKey.value),
  );
  const sortedBookmarks = computed(() =>
    sortBookmarks(currentBrowser.value?.bookmarks ?? [], bookmarkSortKey.value),
  );

  watch(
    browsers,
    (items) => {
      if (!items.length) {
        selectedBrowserId.value = "";
        return;
      }

      const hasSelected = items.some(
        (browser) => browser.browserId === selectedBrowserId.value,
      );

      if (!hasSelected) {
        selectedBrowserId.value = items[0].browserId;
      }
    },
    { immediate: true },
  );

  watch(selectedBrowserId, () => {
    openProfileError.value = "";
    associatedProfilesModal.value = null;
  });

  async function loadBrowserConfigs() {
    configsLoading.value = true;
    configError.value = "";

    try {
      const result = await invoke<BrowserConfigListResponse>("list_browser_configs");
      browserConfigs.value = result.configs;
    } catch (loadError) {
      configError.value =
        loadError instanceof Error ? loadError.message : "Failed to load browser configs.";
    } finally {
      configsLoading.value = false;
    }
  }

  async function scanBrowsers() {
    loading.value = true;
    error.value = "";

    try {
      response.value = await invoke<ScanResponse>("scan_browsers");
    } catch (scanError) {
      error.value =
        scanError instanceof Error
          ? scanError.message
          : "Failed to scan browser data.";
    } finally {
      loading.value = false;
    }
  }

  async function refreshAll() {
    await Promise.all([loadBrowserConfigs(), scanBrowsers()]);
  }

  async function openBrowserProfile(browserId: string, profileId: string) {
    const profileKey = `${browserId}:${profileId}`;
    openingProfileKey.value = profileKey;
    openProfileError.value = "";

    try {
      await invoke("open_browser_profile", {
        browserId,
        profileId,
      });
    } catch (openError) {
      openProfileError.value =
        openError instanceof Error
          ? openError.message
          : "Failed to open the selected browser profile.";
    } finally {
      openingProfileKey.value = "";
    }
  }

  async function createCustomBrowserConfig() {
    savingConfig.value = true;
    configError.value = "";

    try {
      const result = await invoke<BrowserConfigListResponse>("create_custom_browser_config", {
        input: createConfigForm.value,
      });
      browserConfigs.value = result.configs;
      createConfigForm.value = {
        name: "",
        iconKey: "chrome",
        executablePath: "",
        userDataPath: "",
      };
      await scanBrowsers();
    } catch (saveError) {
      configError.value =
        saveError instanceof Error ? saveError.message : "Failed to create browser config.";
    } finally {
      savingConfig.value = false;
    }
  }

  async function deleteCustomBrowserConfig(configId: string) {
    deletingConfigId.value = configId;
    configError.value = "";

    try {
      const result = await invoke<BrowserConfigListResponse>("delete_custom_browser_config", {
        configId,
      });
      browserConfigs.value = result.configs;
      await scanBrowsers();
    } catch (deleteError) {
      configError.value =
        deleteError instanceof Error ? deleteError.message : "Failed to delete browser config.";
    } finally {
      deletingConfigId.value = "";
    }
  }

  async function pickExecutablePath() {
    const selected = await open({
      multiple: false,
      directory: false,
      filters: [
        {
          name: "Executable",
          extensions: ["exe"],
        },
      ],
    });

    if (typeof selected === "string") {
      createConfigForm.value.executablePath = selected;
    }
  }

  async function pickUserDataPath() {
    const selected = await open({
      multiple: false,
      directory: true,
    });

    if (typeof selected === "string") {
      createConfigForm.value.userDataPath = selected;
    }
  }

  function isDeletingConfig(configId: string) {
    return deletingConfigId.value === configId;
  }

  function isOpeningProfile(browserId: string, profileId: string) {
    return openingProfileKey.value === `${browserId}:${profileId}`;
  }

  function browserMonogram(browserId: string) {
    const current = browsers.value.find((browser) => browser.browserId === browserId);
    const iconKey = current?.iconKey ?? current?.browserFamilyId;
    if (iconKey === "chrome") return "CH";
    if (iconKey === "edge") return "ED";
    if (iconKey === "brave") return "BR";

    const name = current?.browserName?.trim() ?? "";
    if (name) {
      const letters = name
        .split(/\s+/)
        .filter(Boolean)
        .slice(0, 2)
        .map((part) => part[0]);
      if (letters.length) return letters.join("").toUpperCase();
    }

    return browserId.slice(0, 2).toUpperCase();
  }

  function configMonogram(config: BrowserConfigEntry) {
    const iconKey = config.iconKey ?? config.browserFamilyId;
    if (iconKey === "chrome") return "CH";
    if (iconKey === "edge") return "ED";
    if (iconKey === "brave") return "BR";

    const letters = config.name
      .trim()
      .split(/\s+/)
      .filter(Boolean)
      .slice(0, 2)
      .map((part) => part[0]);
    return (letters.join("") || config.id.slice(0, 2)).toUpperCase();
  }

  function extensionMonogram(name: string) {
    return name.trim().slice(0, 1).toUpperCase() || "?";
  }

  function domainFromUrl(url: string) {
    try {
      return new URL(url).hostname;
    } catch {
      return url;
    }
  }

  function sectionCount(section: ActiveSection) {
    if (!currentBrowser.value) return 0;
    if (section === "profiles") return currentBrowser.value.profiles.length;
    if (section === "extensions") return currentBrowser.value.extensions.length;
    return currentBrowser.value.bookmarks.length;
  }

  function showExtensionProfilesModal(extensionId: string) {
    const extension = currentBrowser.value?.extensions.find((item) => item.id === extensionId);
    if (!extension || !currentBrowser.value) return;
    associatedProfilesModal.value = {
      title: `${extension.name} Profiles`,
      browserId: currentBrowser.value.browserId,
      profiles: extension.profiles,
      isBookmark: false,
    };
  }

  function showBookmarkProfilesModal(url: string) {
    const bookmark = currentBrowser.value?.bookmarks.find((item) => item.url === url);
    if (!bookmark || !currentBrowser.value) return;
    associatedProfilesModal.value = {
      title: `${bookmark.title} Profiles`,
      browserId: currentBrowser.value.browserId,
      profiles: bookmark.profiles,
      isBookmark: true,
    };
  }

  function closeAssociatedProfilesModal() {
    associatedProfilesModal.value = null;
  }

  onMounted(() => {
    void refreshAll();
  });

  return {
    activeSection,
    associatedProfilesModal,
    bookmarkSortKey,
    browserConfigs,
    browserMonogram,
    browsers,
    configError,
    configMonogram,
    configsLoading,
    createConfigForm,
    createCustomBrowserConfig,
    currentBrowser,
    deleteCustomBrowserConfig,
    domainFromUrl,
    error,
    extensionMonogram,
    extensionSortKey,
    isDeletingConfig,
    isOpeningProfile,
    loading,
    openProfileError,
    openBrowserProfile,
    page,
    pickExecutablePath,
    pickUserDataPath,
    profileSortKey,
    refreshAll,
    savingConfig,
    sectionCount,
    selectedBrowserId,
    showBookmarkProfilesModal,
    showExtensionProfilesModal,
    sortedBookmarks,
    sortedExtensions,
    sortedProfiles,
    closeAssociatedProfilesModal,
  };
}
