<template>
  <div class="sync-settings">
    <!-- G4: persistent conflict alerts sourced from store.syncConflicts
         (populated by the store's handleWsEvent on calendar_sync_conflict). -->
    <a-alert
      v-for="(c, i) in store.syncConflicts"
      :key="`${c.event_id}-${i}`"
      type="warning"
      show-icon
      :message="`同步冲突：${c.event_title}`"
      style="margin-bottom: var(--space-3)"
    >
      <template #description>
        <div class="sync-settings__conflict">
          <div><span class="sync-settings__label">提供商：</span>{{ c.provider }}</div>
          <div><span class="sync-settings__label">本地修改：</span>{{ formatTime(c.local_modified) }}</div>
          <div><span class="sync-settings__label">远端修改：</span>{{ formatTime(c.remote_modified) }}</div>
          <div><span class="sync-settings__label">处理策略：</span>{{ c.resolution }}</div>
        </div>
      </template>
    </a-alert>

    <div class="sync-settings__actions">
      <a-button @click="showAppleForm = true">
        <template #icon><AppleOutlined /></template>
        添加 Apple 日历
      </a-button>
      <!-- ponytail: OAuth callback route (/api/v1/calendar/auth/outlook/callback)
           is deferred — this button only starts the redirect flow; the backend
           will redirect to Microsoft's consent page and back. -->
      <a-button @click="gotoOutlookAuth">
        <template #icon><WindowsOutlined /></template>
        添加 Outlook
      </a-button>
      <a-button :loading="loading" @click="loadConfigs">
        <template #icon><ReloadOutlined /></template>
        刷新
      </a-button>
    </div>

    <a-spin :spinning="loading">
      <a-empty
        v-if="configs.length === 0 && !loading"
        description="尚未配置外部日历"
        style="padding: var(--space-6) 0"
      />
      <div v-else class="sync-settings__list">
        <a-card
          v-for="cfg in configs"
          :key="cfg.id"
          size="small"
          class="sync-settings__card"
        >
          <template #title>
            <div class="sync-settings__card-title">
              <AppleOutlined v-if="cfg.provider === 'caldav'" />
              <WindowsOutlined v-else />
              <span>{{ providerLabel(cfg.provider) }}</span>
              <a-badge status="success" text="已连接" />
            </div>
          </template>
          <template #extra>
            <a-space>
              <a-button size="small" :loading="syncingId === cfg.id" @click="onSync(cfg.id)">
                <template #icon><SyncOutlined /></template>
                立即同步
              </a-button>
              <a-button size="small" :loading="testingId === cfg.id" @click="onTest(cfg.id)">
                <template #icon><ApiOutlined /></template>
                测试连接
              </a-button>
              <a-popconfirm title="确认移除该外部日历？" @confirm="onRemove(cfg.id)">
                <a-button size="small" danger>
                  <template #icon><DeleteOutlined /></template>
                  移除
                </a-button>
              </a-popconfirm>
            </a-space>
          </template>

          <div class="sync-settings__card-body">
            <div class="sync-settings__row">
              <span class="sync-settings__label">上次同步</span>
              <span>{{ cfg.last_sync ? formatTime(cfg.last_sync) : '从未同步' }}</span>
            </div>
            <div class="sync-settings__row">
              <span class="sync-settings__label">同步范围</span>
              <!-- ponytail: no PATCH endpoint for sync_scope yet — edits are
                   local-only until the backend adds an update route. -->
              <a-select
                v-model:value="cfg.sync_scope"
                mode="multiple"
                style="flex: 1; min-width: 200px"
                placeholder="选择要同步的事件类型（留空同步全部）"
                :options="scopeOptions"
                allow-clear
              />
            </div>
          </div>
        </a-card>
      </div>
    </a-spin>

    <!-- Apple Calendar (CalDAV) add form -->
    <a-modal
      :open="showAppleForm"
      title="添加 Apple 日历 (CalDAV)"
      :confirm-loading="submitting"
      ok-text="添加"
      cancel-text="取消"
      @ok="submitApple"
      @cancel="showAppleForm = false"
    >
      <a-form layout="vertical">
        <a-form-item label="CalDAV URL" required>
          <a-input v-model:value="appleForm.url" placeholder="https://caldav.icloud.com" />
        </a-form-item>
        <a-form-item label="Apple ID" required>
          <a-input v-model:value="appleForm.username" placeholder="apple@example.com" />
        </a-form-item>
        <a-form-item label="App 专用密码" required>
          <a-input-password v-model:value="appleForm.password" placeholder="应用专用密码" />
        </a-form-item>
        <a-form-item label="同步范围">
          <a-select
            v-model:value="appleForm.scope"
            mode="multiple"
            placeholder="留空则同步全部"
            :options="scopeOptions"
            allow-clear
          />
        </a-form-item>
      </a-form>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { notification } from 'ant-design-vue'
import {
  AppleOutlined,
  WindowsOutlined,
  SyncOutlined,
  ReloadOutlined,
  ApiOutlined,
  DeleteOutlined,
} from '@ant-design/icons-vue'
import { calendarApi } from '@/api/calendar'
import { useCalendarStore } from '@/stores/calendar'
import type { IExternalCalendarConfig } from '@/api/calendar'

const store = useCalendarStore()

const configs = ref<IExternalCalendarConfig[]>([])
const loading = ref(false)
const syncingId = ref<string | null>(null)
const testingId = ref<string | null>(null)
const submitting = ref(false)

const showAppleForm = ref(false)
const appleForm = ref({
  url: '',
  username: '',
  password: '',
  scope: [] as string[],
})

// ponytail: OAuth callback route is deferred — this URL starts the redirect
// flow only; the backend redirects to Microsoft's consent page.
const OUTLOOK_AUTH_URL = '/api/v1/calendar/auth/outlook'

const scopeOptions = computed(() =>
  store.eventTypes.map((t) => ({ label: t.name, value: t.name })),
)

async function loadConfigs(): Promise<void> {
  loading.value = true
  try {
    const resp = await calendarApi.listExternalConfigs()
    configs.value = resp.configs || []
  } catch (err: unknown) {
    // 后端尚未注册 /external-configs 端点；404 时静默返回空列表
    const status = (err as { status?: number }).status
    if (status === 404 || status === 503) {
      configs.value = []
    } else {
      notification.error({ message: '加载外部日历配置失败' })
    }
    console.warn('listExternalConfigs failed:', err)
  } finally {
    loading.value = false
  }
}

async function onSync(id: string): Promise<void> {
  syncingId.value = id
  try {
    const resp = await calendarApi.syncNow(id)
    if (resp.synced) {
      notification.success({ message: '同步已触发' })
      await loadConfigs()
    } else {
      notification.warning({ message: '同步失败', description: resp.error })
    }
  } catch (err) {
    notification.error({ message: '同步失败' })
    console.warn('syncNow failed:', err)
  } finally {
    syncingId.value = null
  }
}

async function onTest(id: string): Promise<void> {
  testingId.value = id
  try {
    const resp = await calendarApi.testExternalConnection(id)
    if (resp.connected) {
      notification.success({ message: '连接正常' })
    } else {
      notification.warning({ message: '连接失败', description: resp.error })
    }
  } catch (err) {
    notification.error({ message: '测试连接失败' })
    console.warn('testExternalConnection failed:', err)
  } finally {
    testingId.value = null
  }
}

async function onRemove(id: string): Promise<void> {
  try {
    await calendarApi.deleteExternalConfig(id)
    configs.value = configs.value.filter((c) => c.id !== id)
    notification.success({ message: '已移除外部日历' })
  } catch (err) {
    notification.error({ message: '移除失败' })
    console.warn('deleteExternalConfig failed:', err)
  }
}

async function submitApple(): Promise<void> {
  const f = appleForm.value
  if (!f.url || !f.username || !f.password) {
    notification.warning({ message: '请填写完整的 CalDAV 信息' })
    return
  }
  submitting.value = true
  try {
    const credentials = JSON.stringify({
      url: f.url,
      username: f.username,
      password: f.password,
    })
    const resp = await calendarApi.createExternalConfig({
      provider: 'caldav',
      credentials,
      sync_scope: f.scope,
    })
    configs.value.push(resp.config)
    showAppleForm.value = false
    appleForm.value = { url: '', username: '', password: '', scope: [] }
    notification.success({ message: 'Apple 日历已添加' })
  } catch (err) {
    notification.error({ message: '添加失败' })
    console.warn('createExternalConfig failed:', err)
  } finally {
    submitting.value = false
  }
}

function gotoOutlookAuth(): void {
  window.location.href = OUTLOOK_AUTH_URL
}

function providerLabel(p: IExternalCalendarConfig['provider']): string {
  return p === 'caldav' ? 'Apple 日历 (CalDAV)' : 'Outlook'
}

// KTD-11: format ISO timestamps in the user's local timezone.
const dtf = new Intl.DateTimeFormat('zh-CN', {
  year: 'numeric',
  month: '2-digit',
  day: '2-digit',
  hour: '2-digit',
  minute: '2-digit',
  hour12: false,
})

function formatTime(iso: string): string {
  try {
    return dtf.format(new Date(iso))
  } catch {
    return iso
  }
}

onMounted(() => {
  loadConfigs()
  if (store.eventTypes.length === 0) {
    store.loadEventTypes()
  }
})
</script>

<style scoped>
.sync-settings {
  padding: var(--space-2) 0;
}

.sync-settings__actions {
  display: flex;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
  flex-wrap: wrap;
}

.sync-settings__conflict {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: var(--font-sm);
}

.sync-settings__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.sync-settings__card-title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--font-sm);
}

.sync-settings__card-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.sync-settings__row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--font-sm);
}

.sync-settings__label {
  color: var(--text-tertiary);
  min-width: 72px;
  flex-shrink: 0;
}
</style>
