<script setup lang="ts">
import { ref, onMounted } from "vue";
import { useSettingsStore } from "@/stores/settings";
import { useAuthStore } from "@/stores/auth";
import { useToastStore } from "@/stores/toast";
import { apiGet, apiPost, apiPut } from "@/api/client";

const store = useSettingsStore();
const authStore = useAuthStore();
const toastStore = useToastStore();
const assistantName = ref("");
const intentModel = ref("");
const currentPassword = ref("");
const newPassword = ref("");
const confirmNewPassword = ref("");
const changingPassword = ref(false);
const saving = ref(false);
const saved = ref(false);
const exporting = ref(false);
const restoring = ref(false);
const restoreFileInput = ref<HTMLInputElement | null>(null);

// Notification preferences
const notifyTaskReminders = ref(true);
const notifySecurityAlerts = ref(true);
const savingNotifications = ref(false);
const notificationsSaved = ref(false);

// CalDAV settings (per-user)
const caldav = ref({
  caldav_url: "",
  caldav_username: "",
  caldav_password: "",
  caldav_calendar_name: "",
});
const savingCaldav = ref(false);
const caldavSaved = ref(false);
const testingCaldav = ref(false);
const caldavTestResult = ref<{ success: boolean; message?: string; error?: string; calendars?: string[] } | null>(null);

// SMTP settings (admin only)
const smtp = ref({
  smtp_host: "",
  smtp_port: "587",
  smtp_username: "",
  smtp_password: "",
  smtp_from_address: "",
  smtp_from_name: "Fabled Assistant",
  smtp_use_tls: "true",
});
const savingSmtp = ref(false);
const smtpSaved = ref(false);
const testRecipient = ref("");
const sendingTest = ref(false);

// Base URL setting (admin only)
const baseUrl = ref("");
const savingBaseUrl = ref(false);
const baseUrlSaved = ref(false);

onMounted(async () => {
  await store.fetchSettings();
  assistantName.value = store.assistantName;

  // Load notification preferences from user settings
  const allSettings = await apiGet<Record<string, string>>("/api/settings");
  intentModel.value = allSettings.intent_model ?? "";
  if (allSettings.notify_task_reminders !== undefined) {
    notifyTaskReminders.value = allSettings.notify_task_reminders !== "false";
  }
  if (allSettings.notify_security_alerts !== undefined) {
    notifySecurityAlerts.value = allSettings.notify_security_alerts !== "false";
  }

  // Load CalDAV settings
  try {
    const caldavConfig = await apiGet<Record<string, string>>("/api/settings/caldav");
    caldav.value = { ...caldav.value, ...caldavConfig };
  } catch {
    // CalDAV not configured yet
  }

  // Load admin settings
  if (authStore.isAdmin) {
    try {
      const smtpConfig = await apiGet<Record<string, string>>("/api/admin/smtp");
      smtp.value = { ...smtp.value, ...smtpConfig };
    } catch {
      // SMTP not configured yet
    }
    try {
      const urlConfig = await apiGet<{ base_url: string }>("/api/admin/base-url");
      baseUrl.value = urlConfig.base_url;
    } catch {
      // base URL not configured yet
    }
  }
});

async function changePassword() {
  if (newPassword.value !== confirmNewPassword.value) {
    toastStore.show("New passwords do not match", "error");
    return;
  }
  changingPassword.value = true;
  try {
    await apiPut("/api/auth/password", {
      current_password: currentPassword.value,
      new_password: newPassword.value,
    });
    toastStore.show("Password changed successfully");
    currentPassword.value = "";
    newPassword.value = "";
    confirmNewPassword.value = "";
  } catch (e: unknown) {
    if (e && typeof e === "object" && "body" in e) {
      const body = (e as { body?: { error?: string } }).body;
      toastStore.show(body?.error || "Failed to change password", "error");
    } else {
      toastStore.show("Failed to change password", "error");
    }
  } finally {
    changingPassword.value = false;
  }
}

async function saveAssistant() {
  saving.value = true;
  saved.value = false;
  try {
    await store.updateSettings({
      assistant_name: assistantName.value.trim() || "Fable",
      intent_model: intentModel.value.trim(),
    });
    saved.value = true;
    setTimeout(() => (saved.value = false), 2000);
  } finally {
    saving.value = false;
  }
}

async function exportData(scope: "user" | "full") {
  exporting.value = true;
  try {
    const url = scope === "full" ? "/api/admin/backup" : "/api/admin/backup?scope=user";
    const res = await fetch(url);
    if (!res.ok) {
      const body = await res.json().catch(() => ({ error: `Error ${res.status}` }));
      throw new Error((body as Record<string, string>).error || `Error ${res.status}`);
    }
    const data = await res.json();
    const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json" });
    const a = document.createElement("a");
    a.href = URL.createObjectURL(blob);
    a.download = `fabledassistant-backup-${scope}-${new Date().toISOString().slice(0, 10)}.json`;
    a.click();
    URL.revokeObjectURL(a.href);
    toastStore.show("Backup downloaded");
  } catch (e) {
    toastStore.show("Export failed: " + (e as Error).message, "error");
  } finally {
    exporting.value = false;
  }
}

function triggerRestoreUpload() {
  restoreFileInput.value?.click();
}

async function saveNotifications() {
  savingNotifications.value = true;
  notificationsSaved.value = false;
  try {
    await apiPut("/api/settings", {
      notify_task_reminders: notifyTaskReminders.value ? "true" : "false",
      notify_security_alerts: notifySecurityAlerts.value ? "true" : "false",
    });
    notificationsSaved.value = true;
    setTimeout(() => (notificationsSaved.value = false), 2000);
  } catch {
    toastStore.show("Failed to save notification preferences", "error");
  } finally {
    savingNotifications.value = false;
  }
}

async function saveCaldav() {
  savingCaldav.value = true;
  caldavSaved.value = false;
  try {
    await apiPut("/api/settings/caldav", caldav.value);
    caldavSaved.value = true;
    setTimeout(() => (caldavSaved.value = false), 2000);
  } catch {
    toastStore.show("Failed to save CalDAV settings", "error");
  } finally {
    savingCaldav.value = false;
  }
}

async function testCaldav() {
  testingCaldav.value = true;
  caldavTestResult.value = null;
  try {
    const result = await apiPost<{ success: boolean; message?: string; error?: string; calendars?: string[] }>("/api/settings/caldav/test", {});
    caldavTestResult.value = result;
  } catch (e: unknown) {
    if (e && typeof e === "object" && "body" in e) {
      const body = (e as { body?: { error?: string } }).body;
      caldavTestResult.value = { success: false, error: body?.error || "Connection test failed" };
    } else {
      caldavTestResult.value = { success: false, error: "Connection test failed" };
    }
  } finally {
    testingCaldav.value = false;
  }
}

async function saveSmtp() {
  savingSmtp.value = true;
  smtpSaved.value = false;
  try {
    await apiPut("/api/admin/smtp", smtp.value);
    smtpSaved.value = true;
    setTimeout(() => (smtpSaved.value = false), 2000);
  } catch {
    toastStore.show("Failed to save SMTP settings", "error");
  } finally {
    savingSmtp.value = false;
  }
}

async function sendTestEmail() {
  if (!testRecipient.value.trim()) {
    toastStore.show("Enter a recipient email address", "error");
    return;
  }
  sendingTest.value = true;
  try {
    await apiPost("/api/admin/smtp/test", { recipient: testRecipient.value.trim() });
    toastStore.show("Test email sent successfully");
  } catch (e: unknown) {
    if (e && typeof e === "object" && "body" in e) {
      const body = (e as { body?: { error?: string } }).body;
      toastStore.show(body?.error || "Failed to send test email", "error");
    } else {
      toastStore.show("Failed to send test email", "error");
    }
  } finally {
    sendingTest.value = false;
  }
}

async function saveBaseUrl() {
  savingBaseUrl.value = true;
  baseUrlSaved.value = false;
  try {
    await apiPut("/api/admin/base-url", { base_url: baseUrl.value.trim() });
    baseUrlSaved.value = true;
    setTimeout(() => (baseUrlSaved.value = false), 2000);
  } catch {
    toastStore.show("Failed to save application URL", "error");
  } finally {
    savingBaseUrl.value = false;
  }
}

async function handleRestoreFile(event: Event) {
  const file = (event.target as HTMLInputElement).files?.[0];
  if (!file) return;
  restoring.value = true;
  try {
    const text = await file.text();
    const data = JSON.parse(text);
    const res = await fetch("/api/admin/restore", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(data),
    });
    if (!res.ok) {
      const body = await res.json().catch(() => ({ error: `Error ${res.status}` }));
      throw new Error((body as Record<string, string>).error || `Error ${res.status}`);
    }
    const result = await res.json();
    toastStore.show(
      `Restored ${result.stats?.users ?? 0} users, ${result.stats?.notes ?? 0} notes, ${result.stats?.conversations ?? 0} conversations`
    );
  } catch (e) {
    toastStore.show("Restore failed: " + (e as Error).message, "error");
  } finally {
    restoring.value = false;
    // Reset file input
    if (restoreFileInput.value) restoreFileInput.value.value = "";
  }
}
</script>

<template>
  <main class="settings-page">
    <h1>Settings</h1>

    <section class="settings-section">
      <h2>Assistant</h2>
      <div class="field">
        <label for="assistant-name">Assistant Name</label>
        <input
          id="assistant-name"
          v-model="assistantName"
          type="text"
          placeholder="Fable"
          class="input"
        />
        <p class="field-hint">
          The name used for the AI assistant in chat messages and LLM context.
        </p>
      </div>

      <div class="field">
        <label for="intent-model">Intent Model</label>
        <input
          id="intent-model"
          v-model="intentModel"
          type="text"
          placeholder="Same as chat model"
          class="input"
        />
        <p class="field-hint">
          Optional smaller/faster model for intent routing (e.g. <code>llama3.2:3b</code>,
          <code>qwen2.5:3b</code>). Leave empty to use the same model as chat.
          Can also be set via <code>OLLAMA_INTENT_MODEL</code> environment variable.
        </p>
      </div>

      <div class="actions">
        <button class="btn-save" @click="saveAssistant" :disabled="saving">
          {{ saving ? "Saving..." : "Save" }}
        </button>
        <span v-if="saved" class="saved-msg">Saved!</span>
      </div>
    </section>

    <section class="settings-section">
      <h2>Change Password</h2>
      <div class="field">
        <label for="current-password">Current Password</label>
        <input
          id="current-password"
          v-model="currentPassword"
          type="password"
          autocomplete="current-password"
          class="input"
        />
      </div>
      <div class="field">
        <label for="new-password">New Password</label>
        <input
          id="new-password"
          v-model="newPassword"
          type="password"
          autocomplete="new-password"
          class="input"
        />
        <p class="field-hint">Must be at least 8 characters</p>
      </div>
      <div class="field">
        <label for="confirm-new-password">Confirm New Password</label>
        <input
          id="confirm-new-password"
          v-model="confirmNewPassword"
          type="password"
          autocomplete="new-password"
          class="input"
          :class="{ 'input-error': confirmNewPassword && newPassword !== confirmNewPassword }"
        />
        <p v-if="confirmNewPassword && newPassword !== confirmNewPassword" class="error-hint">
          Passwords do not match
        </p>
      </div>
      <div class="actions">
        <button
          class="btn-save"
          @click="changePassword"
          :disabled="changingPassword || !currentPassword || newPassword.length < 8 || newPassword !== confirmNewPassword"
        >
          {{ changingPassword ? "Changing..." : "Change Password" }}
        </button>
      </div>
    </section>

    <section class="settings-section">
      <h2>Notifications</h2>
      <p class="section-desc">
        Choose which email notifications you'd like to receive. Requires SMTP to be configured by an admin.
      </p>

      <div class="checkbox-field">
        <label>
          <input type="checkbox" v-model="notifyTaskReminders" />
          Task due date reminders
        </label>
        <p class="field-hint">Receive a daily email when you have tasks due or overdue.</p>
      </div>
      <div class="checkbox-field">
        <label>
          <input type="checkbox" v-model="notifySecurityAlerts" />
          Security alerts
        </label>
        <p class="field-hint">Receive emails for login, logout, failed login attempts, and password changes.</p>
      </div>
      <div class="actions">
        <button class="btn-save" @click="saveNotifications" :disabled="savingNotifications">
          {{ savingNotifications ? "Saving..." : "Save" }}
        </button>
        <span v-if="notificationsSaved" class="saved-msg">Saved!</span>
      </div>
    </section>

    <section class="settings-section">
      <h2>Calendar (CalDAV)</h2>
      <p class="section-desc">
        Connect to a CalDAV server (Nextcloud, iCloud, Radicale, Baikal) to create and view calendar events from chat.
      </p>

      <div class="caldav-grid">
        <div class="field">
          <label for="caldav-url">CalDAV URL</label>
          <input id="caldav-url" v-model="caldav.caldav_url" type="url" placeholder="https://cloud.example.com/remote.php/dav" class="input" />
        </div>
        <div class="field">
          <label for="caldav-username">Username</label>
          <input id="caldav-username" v-model="caldav.caldav_username" type="text" class="input" />
        </div>
        <div class="field">
          <label for="caldav-password">Password</label>
          <input id="caldav-password" v-model="caldav.caldav_password" type="password" class="input" />
        </div>
        <div class="field">
          <label for="caldav-calendar-name">Calendar Name</label>
          <input id="caldav-calendar-name" v-model="caldav.caldav_calendar_name" type="text" placeholder="Leave empty to use first available" class="input" />
          <p class="field-hint">Optional. The exact name of the calendar to use.</p>
        </div>
      </div>

      <div class="actions" style="margin-bottom: 1rem;">
        <button class="btn-save" @click="saveCaldav" :disabled="savingCaldav">
          {{ savingCaldav ? "Saving..." : "Save" }}
        </button>
        <span v-if="caldavSaved" class="saved-msg">Saved!</span>
        <button class="btn-save btn-test" @click="testCaldav" :disabled="testingCaldav">
          {{ testingCaldav ? "Testing..." : "Test Connection" }}
        </button>
      </div>

      <div v-if="caldavTestResult" class="test-result" :class="{ success: caldavTestResult.success, error: !caldavTestResult.success }">
        <template v-if="caldavTestResult.success">
          {{ caldavTestResult.message }}
          <div v-if="caldavTestResult.calendars?.length" class="test-calendars">
            Calendars: {{ caldavTestResult.calendars.join(", ") }}
          </div>
        </template>
        <template v-else>
          {{ caldavTestResult.error }}
        </template>
      </div>
    </section>

    <section v-if="authStore.isAdmin" class="settings-section">
      <h2>Application URL</h2>
      <p class="section-desc">
        The public URL used in email links (invitations, password resets). Example: https://notes.example.com
      </p>
      <div class="field">
        <label for="base-url">Base URL</label>
        <input
          id="base-url"
          v-model="baseUrl"
          type="url"
          placeholder="https://notes.example.com"
          class="input"
        />
      </div>
      <div class="actions">
        <button class="btn-save" @click="saveBaseUrl" :disabled="savingBaseUrl">
          {{ savingBaseUrl ? "Saving..." : "Save" }}
        </button>
        <span v-if="baseUrlSaved" class="saved-msg">Saved!</span>
      </div>
    </section>

    <section v-if="authStore.isAdmin" class="settings-section">
      <h2>Email / SMTP</h2>
      <p class="section-desc">
        Configure SMTP settings to enable email notifications for all users.
      </p>

      <div class="smtp-grid">
        <div class="field">
          <label for="smtp-host">SMTP Host</label>
          <input id="smtp-host" v-model="smtp.smtp_host" type="text" placeholder="smtp.example.com" class="input" />
        </div>
        <div class="field">
          <label for="smtp-port">Port</label>
          <input id="smtp-port" v-model="smtp.smtp_port" type="text" placeholder="587" class="input" />
        </div>
        <div class="field">
          <label for="smtp-username">Username</label>
          <input id="smtp-username" v-model="smtp.smtp_username" type="text" class="input" />
        </div>
        <div class="field">
          <label for="smtp-password">Password</label>
          <input id="smtp-password" v-model="smtp.smtp_password" type="password" class="input" />
        </div>
        <div class="field">
          <label for="smtp-from-address">From Address</label>
          <input id="smtp-from-address" v-model="smtp.smtp_from_address" type="email" placeholder="noreply@example.com" class="input" />
        </div>
        <div class="field">
          <label for="smtp-from-name">From Name</label>
          <input id="smtp-from-name" v-model="smtp.smtp_from_name" type="text" placeholder="Fabled Assistant" class="input" />
        </div>
      </div>

      <div class="checkbox-field">
        <label>
          <input type="checkbox" :checked="smtp.smtp_use_tls === 'true'" @change="smtp.smtp_use_tls = ($event.target as HTMLInputElement).checked ? 'true' : 'false'" />
          Use STARTTLS
        </label>
        <p class="field-hint">Enable STARTTLS encryption (recommended for port 587). Implicit TLS is used automatically for port 465.</p>
      </div>

      <div class="actions" style="margin-bottom: 1.25rem;">
        <button class="btn-save" @click="saveSmtp" :disabled="savingSmtp">
          {{ savingSmtp ? "Saving..." : "Save SMTP Settings" }}
        </button>
        <span v-if="smtpSaved" class="saved-msg">Saved!</span>
      </div>

      <div class="test-email-section">
        <h3 class="subsection-label">Test Email</h3>
        <div class="test-email-row">
          <input
            v-model="testRecipient"
            type="email"
            placeholder="test@example.com"
            class="input"
            style="flex: 1;"
          />
          <button class="btn-save" @click="sendTestEmail" :disabled="sendingTest || !testRecipient.trim()">
            {{ sendingTest ? "Sending..." : "Send Test" }}
          </button>
        </div>
      </div>
    </section>

    <section class="settings-section">
      <h2>Data</h2>
      <p class="section-desc">Export your data or restore from a backup.</p>

      <div class="data-actions">
        <button
          class="btn-export"
          @click="exportData('user')"
          :disabled="exporting"
        >
          {{ exporting ? "Exporting..." : "Export My Data" }}
        </button>

        <template v-if="authStore.isAdmin">
          <button
            class="btn-export"
            @click="exportData('full')"
            :disabled="exporting"
          >
            {{ exporting ? "Exporting..." : "Export Full Backup" }}
          </button>
          <button
            class="btn-restore"
            @click="triggerRestoreUpload"
            :disabled="restoring"
          >
            {{ restoring ? "Restoring..." : "Restore from Backup" }}
          </button>
          <input
            ref="restoreFileInput"
            type="file"
            accept=".json"
            class="hidden-file-input"
            @change="handleRestoreFile"
          />
        </template>
      </div>
    </section>
  </main>
</template>

<style scoped>
.settings-page {
  max-width: 960px;
  margin: 2rem auto;
  padding: 0 1rem;
}
.settings-page h1 {
  margin: 0 0 1.5rem;
}
.settings-section {
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 1.25rem;
  margin-bottom: 1.5rem;
}
.settings-section h2 {
  margin: 0 0 0.5rem;
  font-size: 1.1rem;
}
.section-desc {
  margin: 0 0 1rem;
  font-size: 0.9rem;
  color: var(--color-text-secondary);
}
.field {
  margin-bottom: 1rem;
}
.field label {
  display: block;
  font-size: 0.9rem;
  font-weight: 600;
  margin-bottom: 0.35rem;
  color: var(--color-text);
}
.input {
  width: 100%;
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: 0.95rem;
  background: var(--color-bg);
  color: var(--color-text);
  box-sizing: border-box;
}
.input:focus {
  outline: none;
  border-color: var(--color-primary);
}
.field-hint {
  margin: 0.35rem 0 0;
  font-size: 0.8rem;
  color: var(--color-text-muted);
}
.actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
.btn-save {
  padding: 0.45rem 1rem;
  background: var(--color-primary);
  color: #fff;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 0.9rem;
}
.btn-save:disabled {
  opacity: 0.6;
  cursor: default;
}
.btn-save:hover:not(:disabled) {
  opacity: 0.9;
}
.saved-msg {
  color: var(--color-success);
  font-size: 0.9rem;
  font-weight: 600;
}
.input-error {
  border-color: var(--color-danger);
}
.input-error:focus {
  border-color: var(--color-danger);
}
.error-hint {
  margin: 0.35rem 0 0;
  font-size: 0.8rem;
  color: var(--color-danger);
}

/* Data section */
.data-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.btn-export {
  padding: 0.45rem 1rem;
  background: var(--color-bg-secondary);
  color: var(--color-text);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 0.9rem;
}
.btn-export:hover:not(:disabled) {
  border-color: var(--color-primary);
  color: var(--color-primary);
}
.btn-export:disabled {
  opacity: 0.6;
  cursor: default;
}
.btn-restore {
  padding: 0.45rem 1rem;
  background: var(--color-bg-secondary);
  color: var(--color-text);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 0.9rem;
}
.btn-restore:hover:not(:disabled) {
  border-color: var(--color-warning);
  color: var(--color-warning);
}
.btn-restore:disabled {
  opacity: 0.6;
  cursor: default;
}
.hidden-file-input {
  display: none;
}

/* Checkbox fields */
.checkbox-field {
  margin-bottom: 1rem;
}
.checkbox-field label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.95rem;
  color: var(--color-text);
  cursor: pointer;
}
.checkbox-field input[type="checkbox"] {
  width: 16px;
  height: 16px;
  accent-color: var(--color-primary);
}

/* CalDAV grid */
.caldav-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 1rem;
}
@media (max-width: 480px) {
  .caldav-grid {
    grid-template-columns: 1fr;
  }
}
.btn-test {
  background: var(--color-bg-secondary);
  color: var(--color-text);
  border: 1px solid var(--color-border);
}
.btn-test:hover:not(:disabled) {
  border-color: var(--color-primary);
  color: var(--color-primary);
  opacity: 1;
}
.test-result {
  padding: 0.75rem 1rem;
  border-radius: var(--radius-sm);
  font-size: 0.9rem;
  line-height: 1.4;
}
.test-result.success {
  background: color-mix(in srgb, var(--color-success) 10%, var(--color-bg));
  border: 1px solid var(--color-success);
  color: var(--color-success);
}
.test-result.error {
  background: color-mix(in srgb, var(--color-danger) 10%, var(--color-bg));
  border: 1px solid var(--color-danger);
  color: var(--color-danger);
}
.test-calendars {
  margin-top: 0.35rem;
  font-size: 0.85rem;
  opacity: 0.85;
}

/* SMTP grid */
.smtp-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 1rem;
}
@media (max-width: 480px) {
  .smtp-grid {
    grid-template-columns: 1fr;
  }
}

/* Test email */
.subsection-label {
  margin: 0 0 0.5rem;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--color-text-secondary);
}
.test-email-section {
  border-top: 1px solid var(--color-border);
  padding-top: 1rem;
}
.test-email-row {
  display: flex;
  gap: 0.5rem;
  align-items: center;
}
</style>
