import { Alpine } from "./alpine";
import { showToast } from "./toast";
import { getToken } from "./storage";

function getDeviceIcon(typeName: string): string {
  const deviceIcons: Record<string, string> = {
    koreader: "📖",
    kobo: "📚",
    web: "🌐",
    mobile: "📱",
  };
  return deviceIcons[typeName] || "📱";
}

function showAddDeviceModal(): void {
  const modal = document.getElementById("add-device-modal");
  if (modal) modal.classList.remove("hidden");
}

function hideAddDeviceModal(): void {
  const modal = document.getElementById("add-device-modal");
  const form = document.getElementById("add-device-form");
  if (modal) modal.classList.add("hidden");
  if (form && form instanceof HTMLFormElement) form.reset();
}

async function handleAddDevice(event: Event): Promise<void> {
  event.preventDefault();

  const token = getToken();
  if (!token) return;

  const deviceNameInput = document.getElementById(
    "device-name",
  ) as HTMLInputElement;
  const deviceTypeInput = document.getElementById(
    "device-type",
  ) as HTMLSelectElement;
  const deviceIdentifierInput = document.getElementById(
    "device-identifier",
  ) as HTMLInputElement;

  if (!deviceNameInput || !deviceTypeInput || !deviceIdentifierInput) return;

  const data = {
    device_name: deviceNameInput.value,
    device_type: deviceTypeInput.value,
    device_identifier: deviceIdentifierInput.value,
  };

  try {
    const response = await fetch("/api/devices/register", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${token}`,
      },
      body: JSON.stringify(data),
    });

    if (response.ok) {
      showToast(
        "Device registered! Check your device for sync instructions.",
        "success",
      );
      hideAddDeviceModal();
      window.location.reload();
    } else {
      showToast("Failed to register device", "error");
    }
  } catch (error) {
    console.error("Failed to register device", error);
    showToast("Failed to register device", "error");
  }
}

function showDeviceSettings(deviceId: string): void {
  const modal = document.getElementById("device-settings-modal");
  const deviceIdInput = document.getElementById(
    "settings-device-id",
  ) as HTMLInputElement;
  const deviceTypeInput = document.getElementById(
    "settings-device-type",
  ) as HTMLInputElement;
  const deviceNameInput = document.getElementById(
    "settings-device-name",
  ) as HTMLInputElement;
  const syncEnabledInput = document.getElementById(
    "settings-sync-enabled",
  ) as HTMLInputElement;
  const autoSyncInput = document.getElementById(
    "settings-auto-sync",
  ) as HTMLInputElement;
  const syncFrequencyInput = document.getElementById(
    "settings-sync-frequency",
  ) as HTMLInputElement;

  if (!modal || !deviceIdInput) return;

  deviceIdInput.value = deviceId;

  const token = getToken();
  if (!token) return;

  let deviceType: any;

  fetch(`/api/devices/${deviceId}`, {
    headers: { Authorization: `Bearer ${token}` },
  })
    .then((res) => res.json())
    .then((device) => {
      if (deviceTypeInput) deviceTypeInput.value = device.device_type || "";
      if (deviceNameInput) deviceNameInput.value = device.device_name || "";
      if (syncEnabledInput)
        syncEnabledInput.checked = device.sync_enabled || false;
      if (autoSyncInput) autoSyncInput.checked = device.auto_sync || false;
      if (syncFrequencyInput)
        syncFrequencyInput.value = String(device.sync_frequency_minutes || 60);

      deviceType = device.device_type;
      return fetch("/api/collections", {
        headers: { Authorization: `Bearer ${token}` },
      });
    })
    .then((res) => res.json())
    .then((result) => {
      if (result.collections && result.collections.length > 0) {
        const firstCollection = result.collections[0];
        const viewSettings = firstCollection.view_settings || {};
        const deviceSettings = viewSettings[deviceType] || {};

        const viewModeInput = document.getElementById(
          "settings-view-mode",
        ) as HTMLInputElement;
        const sortOrderInput = document.getElementById(
          "settings-sort-order",
        ) as HTMLInputElement;
        const itemsPerPageInput = document.getElementById(
          "settings-items-per-page",
        ) as HTMLInputElement;
        const showCoversInput = document.getElementById(
          "settings-show-covers",
        ) as HTMLInputElement;
        const showProgressInput = document.getElementById(
          "settings-show-progress",
        ) as HTMLInputElement;

        if (viewModeInput)
          viewModeInput.value = deviceSettings.view_mode || "grid";
        if (sortOrderInput)
          sortOrderInput.value = deviceSettings.sort_order || "name";
        if (itemsPerPageInput)
          itemsPerPageInput.value = String(deviceSettings.items_per_page || 24);
        if (showCoversInput)
          showCoversInput.checked = deviceSettings.show_covers !== false;
        if (showProgressInput)
          showProgressInput.checked = deviceSettings.show_progress || false;
      }
    })
    .catch((error) => {
      console.error("Failed to load view settings:", error);
    });

  if (modal) modal.classList.remove("hidden");
}

function showShelfMappings(deviceId: string): void {
  const mappingsDeviceIdInput = document.getElementById(
    "mappings-device-id",
  ) as HTMLInputElement;
  const modal = document.getElementById("shelf-mappings-modal");

  if (mappingsDeviceIdInput) mappingsDeviceIdInput.value = deviceId;
  loadShelfMappings(deviceId);
  if (modal) modal.classList.remove("hidden");
}

function hideShelfMappingsModal(): void {
  const modal = document.getElementById("shelf-mappings-modal");
  if (modal) modal.classList.add("hidden");
}

async function loadShelfMappings(deviceId: string): Promise<void> {
  const container = document.getElementById("shelf-mappings-container");
  const token = getToken();
  if (!container || !token) return;

  try {
    const response = await fetch(`/api/devices/${deviceId}/collections`, {
      headers: { Authorization: `Bearer ${token}` },
    });
    const result = await response.json();

    if (result.mappings && result.mappings.length > 0) {
      container.innerHTML = result.mappings
        .map(
          (mapping: any) => `
          <div class="card p-4 rounded-lg border" style="background-color: var(--bg-primary); border-color: var(--border);">
            <div class="flex justify-between items-center">
              <div>
                <h4 class="font-semibold" style="color: var(--text-primary)">${mapping.collection_name}</h4>
                <p class="text-sm" style="color: var(--text-secondary)">
                  → Device Shelf: <strong>${mapping.device_shelf_name}</strong>
                </p>
                <p class="text-xs" style="color: var(--text-secondary)">
                  Sync: ${mapping.sync_direction}
                </p>
              </div>
              <div class="flex space-x-2">
                <button data-action="edit-mapping" data-mapping-id="${mapping.id}" data-collection-id="${mapping.collection_id}" data-shelf-name="${mapping.device_shelf_name}" data-sync-direction="${mapping.sync_direction}"
                  class="p-2 hover:opacity-80 rounded" style="color: var(--text-secondary); background-color: var(--bg-secondary);">
                  ✏️
                </button>
                <button data-action="delete-mapping" data-mapping-id="${mapping.id}"
                  class="p-2 hover:opacity-80 rounded" style="color: var(--text-secondary); background-color: var(--bg-secondary);">
                  🗑️
                </button>
              </div>
            </div>
          </div>
        `,
        )
        .join("");
    } else {
      container.innerHTML =
        '<p style="color: var(--text-secondary)">No shelf mappings configured. Click "Add Mapping" to create one.</p>';
    }
  } catch (error) {
    container.innerHTML =
      '<p style="color: var(--error)">Failed to load mappings</p>';
  }
}

function showAddMappingModal(): void {
  const mappingsDeviceIdInput = document.getElementById(
    "mappings-device-id",
  ) as HTMLInputElement;
  const mappingIdInput = document.getElementById(
    "mapping-id",
  ) as HTMLInputElement;
  const mappingCollectionInput = document.getElementById(
    "mapping-collection",
  ) as HTMLSelectElement;
  const mappingShelfNameInput = document.getElementById(
    "mapping-shelf-name",
  ) as HTMLInputElement;
  const mappingSyncDirectionInput = document.getElementById(
    "mapping-sync-direction",
  ) as HTMLSelectElement;
  const modal = document.getElementById("add-mapping-modal");

  if (mappingsDeviceIdInput) {
    const mappingDeviceIdInput = document.getElementById(
      "mapping-device-id",
    ) as HTMLInputElement;
    if (mappingDeviceIdInput)
      mappingDeviceIdInput.value = mappingsDeviceIdInput.value;
  }
  if (mappingIdInput) mappingIdInput.value = "";
  if (mappingCollectionInput) mappingCollectionInput.value = "";
  if (mappingShelfNameInput) mappingShelfNameInput.value = "";
  if (mappingSyncDirectionInput)
    mappingSyncDirectionInput.value = "bidirectional";

  loadCollections();
  if (modal) modal.classList.remove("hidden");
}

function hideAddMappingModal(): void {
  const modal = document.getElementById("add-mapping-modal");
  const form = document.getElementById("mapping-form");
  if (modal) modal.classList.add("hidden");
  if (form && form instanceof HTMLFormElement) form.reset();
}

async function loadCollections(): Promise<void> {
  const select = document.getElementById(
    "mapping-collection",
  ) as HTMLSelectElement;
  const token = getToken();
  if (!select || !token) return;

  try {
    const response = await fetch("/api/collections", {
      headers: { Authorization: `Bearer ${token}` },
    });
    const result = await response.json();

    if (result.collections) {
      select.innerHTML =
        '<option value="">Select collection...</option>' +
        result.collections
          .map((col: any) => `<option value="${col.id}">${col.name}</option>`)
          .join("");
    }
  } catch (error) {
    console.error("Failed to load collections", error);
  }
}

function editMapping(
  mappingId: string,
  collectionId: string,
  shelfName: string,
  syncDirection: string,
): void {
  const mappingIdInput = document.getElementById(
    "mapping-id",
  ) as HTMLInputElement;
  const mappingCollectionInput = document.getElementById(
    "mapping-collection",
  ) as HTMLSelectElement;
  const mappingShelfNameInput = document.getElementById(
    "mapping-shelf-name",
  ) as HTMLInputElement;
  const mappingSyncDirectionInput = document.getElementById(
    "mapping-sync-direction",
  ) as HTMLSelectElement;
  const modal = document.getElementById("add-mapping-modal");

  if (mappingIdInput) mappingIdInput.value = mappingId;
  if (mappingCollectionInput) mappingCollectionInput.value = collectionId;
  if (mappingShelfNameInput) mappingShelfNameInput.value = shelfName;
  if (mappingSyncDirectionInput)
    mappingSyncDirectionInput.value = syncDirection;

  if (modal) modal.classList.remove("hidden");
}

async function handleSaveMapping(event: Event): Promise<void> {
  event.preventDefault();

  const token = getToken();
  const mappingsDeviceIdInput = document.getElementById(
    "mapping-device-id",
  ) as HTMLInputElement;
  const mappingIdInput = document.getElementById(
    "mapping-id",
  ) as HTMLInputElement;
  const mappingCollectionInput = document.getElementById(
    "mapping-collection",
  ) as HTMLSelectElement;
  const mappingShelfNameInput = document.getElementById(
    "mapping-shelf-name",
  ) as HTMLInputElement;
  const mappingSyncDirectionInput = document.getElementById(
    "mapping-sync-direction",
  ) as HTMLSelectElement;

  if (
    !token ||
    !mappingsDeviceIdInput ||
    !mappingCollectionInput ||
    !mappingShelfNameInput ||
    !mappingSyncDirectionInput
  )
    return;

  const deviceId = mappingsDeviceIdInput.value;
  const mappingId = mappingIdInput.value;
  const isUpdate = mappingId !== "";

  const data = {
    collection_id: mappingCollectionInput.value,
    device_shelf_name: mappingShelfNameInput.value,
    sync_direction: mappingSyncDirectionInput.value,
  };

  const url = isUpdate
    ? `/api/devices/${deviceId}/collections/${mappingId}`
    : `/api/devices/${deviceId}/collections`;
  const method = isUpdate ? "PUT" : "POST";

  try {
    const response = await fetch(url, {
      method: method,
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${token}`,
      },
      body: JSON.stringify(data),
    });

    if (response.ok) {
      showToast(isUpdate ? "Mapping updated" : "Mapping created", "success");
      hideAddMappingModal();
      loadShelfMappings(deviceId);
    } else {
      showToast("Failed to save mapping", "error");
    }
  } catch (error) {
    console.error("Failed to save mapping", error);
    showToast("Failed to save mapping", "error");
  }
}

async function deleteMapping(mappingId: string): Promise<void> {
  if (!confirm("Are you sure you want to delete this mapping?")) return;

  const token = getToken();
  const mappingsDeviceIdInput = document.getElementById(
    "mappings-device-id",
  ) as HTMLInputElement;
  if (!token || !mappingsDeviceIdInput) return;

  const deviceId = mappingsDeviceIdInput.value;

  try {
    const response = await fetch(
      `/api/devices/${deviceId}/collections/${mappingId}`,
      {
        method: "DELETE",
        headers: { Authorization: `Bearer ${token}` },
      },
    );

    if (response.ok) {
      showToast("Mapping deleted", "success");
      loadShelfMappings(deviceId);
    } else {
      showToast("Failed to delete mapping", "error");
    }
  } catch (error) {
    console.error("Failed to delete mapping", error);
    showToast("Failed to delete mapping", "error");
  }
}

function hideDeviceSettingsModal(): void {
  const modal = document.getElementById("device-settings-modal");
  if (modal) modal.classList.add("hidden");
}

async function handleSaveDeviceSettings(event: Event): Promise<void> {
  event.preventDefault();

  const token = getToken();
  const settingsDeviceIdInput = document.getElementById(
    "settings-device-id",
  ) as HTMLInputElement;
  const settingsDeviceTypeInput = document.getElementById(
    "settings-device-type",
  ) as HTMLInputElement;
  const settingsDeviceNameInput = document.getElementById(
    "settings-device-name",
  ) as HTMLInputElement;
  const settingsSyncEnabledInput = document.getElementById(
    "settings-sync-enabled",
  ) as HTMLInputElement;
  const settingsAutoSyncInput = document.getElementById(
    "settings-auto-sync",
  ) as HTMLInputElement;
  const settingsSyncFrequencyInput = document.getElementById(
    "settings-sync-frequency",
  ) as HTMLInputElement;

  if (!token || !settingsDeviceIdInput || !settingsDeviceNameInput) return;

  const deviceId = settingsDeviceIdInput.value;
  const deviceType = settingsDeviceTypeInput?.value || "";

  const deviceData = {
    device_name: settingsDeviceNameInput.value,
    sync_enabled: settingsSyncEnabledInput?.checked || false,
    auto_sync: settingsAutoSyncInput?.checked || false,
    sync_frequency_minutes: parseInt(
      settingsSyncFrequencyInput?.value || "60",
      10,
    ),
  };

  const viewModeInput = document.getElementById(
    "settings-view-mode",
  ) as HTMLSelectElement;
  const sortOrderInput = document.getElementById(
    "settings-sort-order",
  ) as HTMLSelectElement;
  const itemsPerPageInput = document.getElementById(
    "settings-items-per-page",
  ) as HTMLInputElement;
  const showCoversInput = document.getElementById(
    "settings-show-covers",
  ) as HTMLInputElement;
  const showProgressInput = document.getElementById(
    "settings-show-progress",
  ) as HTMLInputElement;

  const viewSettings = {
    view_mode: viewModeInput?.value || "grid",
    sort_order: sortOrderInput?.value || "name",
    items_per_page: parseInt(itemsPerPageInput?.value || "24", 10),
    show_covers: showCoversInput?.checked !== false,
    show_progress: showProgressInput?.checked || false,
  };

  try {
    await fetch(`/api/devices/${deviceId}`, {
      method: "PUT",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${token}`,
      },
      body: JSON.stringify(deviceData),
    });

    const collectionsRes = await fetch("/api/collections", {
      method: "GET",
      headers: { Authorization: `Bearer ${token}` },
    });
    const collections = await collectionsRes.json();

    const updatePromises = collections.collections.map((collection: any) => {
      const currentSettings = collection.view_settings || {};
      currentSettings[deviceType] = viewSettings;

      return fetch(`/api/collections/${collection.id}`, {
        method: "PUT",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${token}`,
        },
        body: JSON.stringify({
          ...collection,
          view_settings: currentSettings,
        }),
      });
    });

    await Promise.all(updatePromises);
    showToast("Device settings saved", "success");
    hideDeviceSettingsModal();
    window.location.reload();
  } catch (error) {
    console.error("Failed to save settings", error);
    showToast("Failed to save settings", "error");
  }
}

async function copyToClipboard(
  text: string,
  description: string,
): Promise<void> {
  try {
    await navigator.clipboard.writeText(text);
    showToast(`${description} copied!`, "success");
  } catch (error) {
    console.error("Failed to copy to clipboard", error);
    showToast("Failed to copy to clipboard", "error");
  }
}

async function handleRevokeDevice(): Promise<void> {
  const token = getToken();
  const settingsDeviceIdInput = document.getElementById(
    "settings-device-id",
  ) as HTMLInputElement;
  if (!token || !settingsDeviceIdInput) return;

  if (
    !confirm(
      "Are you sure you want to revoke this device? It will no longer be able to sync.",
    )
  )
    return;

  const deviceId = settingsDeviceIdInput.value;

  try {
    const response = await fetch(`/api/devices/${deviceId}`, {
      method: "DELETE",
      headers: { Authorization: `Bearer ${token}` },
    });

    if (response.ok) {
      showToast("Device revoked successfully", "success");
      hideDeviceSettingsModal();
      window.location.reload();
    } else {
      showToast("Failed to revoke device", "error");
    }
  } catch (error) {
    console.error("Failed to revoke device", error);
    showToast("Failed to revoke device", "error");
  }
}

async function approveDevice(registrationId: string): Promise<void> {
  const token = getToken();
  if (!token) return;

  try {
    const response = await fetch(`/api/devices/approve/${registrationId}`, {
      method: "GET",
      headers: { Authorization: `Bearer ${token}` },
    });

    if (response.ok) {
      showToast("Device approved successfully", "success");
      window.location.reload();
    } else {
      showToast("Failed to approve device", "error");
    }
  } catch (error) {
    console.error("Failed to approve device", error);
    showToast("Failed to approve device", "error");
  }
}

async function rejectDevice(registrationId: string): Promise<void> {
  const token = getToken();
  if (!token) return;

  try {
    const response = await fetch(`/api/devices/reject/${registrationId}`, {
      method: "POST",
      headers: { Authorization: `Bearer ${token}` },
    });

    if (response.ok) {
      showToast("Device registration rejected", "info");
      window.location.reload();
    } else {
      showToast("Failed to reject device", "error");
    }
  } catch (error) {
    console.error("Failed to reject device", error);
    showToast("Failed to reject device", "error");
  }
}

async function clearSyncQueue(): Promise<void> {
  if (!confirm("Are you sure you want to clear all sync queue items?")) return;

  const token = getToken();
  if (!token) return;

  try {
    const response = await fetch("/api/queue/clear", {
      method: "DELETE",
      headers: { Authorization: `Bearer ${token}` },
    });

    if (response.ok) {
      showToast("Sync queue cleared", "success");
    } else {
      showToast("Failed to clear queue", "error");
    }
  } catch (error) {
    console.error("Failed to clear queue", error);
    showToast("Failed to clear queue", "error");
  }
}

function setupEventDelegation(): void {
  document.addEventListener("click", (e) => {
    const target = e.target as HTMLElement;
    const button = target.closest("button") as HTMLButtonElement;

    if (!button) return;

    const action = button.dataset.action;

    if (action === "edit-mapping") {
      editMapping(
        button.dataset.mappingId || "",
        button.dataset.collectionId || "",
        button.dataset.shelfName || "",
        button.dataset.syncDirection || "",
      );
    } else if (action === "delete-mapping") {
      deleteMapping(button.dataset.mappingId || "");
    }
  });
}

export {
  approveDevice,
  clearSyncQueue,
  copyToClipboard,
  deleteMapping,
  editMapping,
  getDeviceIcon,
  handleAddDevice,
  handleRevokeDevice,
  handleSaveDeviceSettings,
  handleSaveMapping,
  hideAddDeviceModal,
  hideAddMappingModal,
  hideDeviceSettingsModal,
  hideShelfMappingsModal,
  loadCollections,
  loadShelfMappings,
  rejectDevice,
  setupEventDelegation,
  showAddDeviceModal,
  showAddMappingModal,
  showDeviceSettings,
  showShelfMappings,
};

Alpine.data("devices", () => ({
  approveDevice,
  clearSyncQueue,
  copyToClipboard,
  deleteMapping,
  editMapping,
  getDeviceIcon,
  handleAddDevice,
  handleRevokeDevice,
  handleSaveDeviceSettings,
  handleSaveMapping,
  hideAddDeviceModal,
  hideAddMappingModal,
  hideDeviceSettingsModal,
  hideShelfMappingsModal,
  loadCollections,
  loadShelfMappings,
  rejectDevice,
  setupEventDelegation,
  showAddDeviceModal,
  showAddMappingModal,
  showDeviceSettings,
  showShelfMappings,
}));
