<script setup lang="ts">
import { computed, onMounted, ref } from "vue";
import { providerProfilesAPI } from "@/api";
import ApiErrorDiagnostic from "@/components/common/ApiErrorDiagnostic.vue";
import BaseDialog from "@/components/common/BaseDialog.vue";
import ConfirmDialog from "@/components/common/ConfirmDialog.vue";
import DataTable from "@/components/common/DataTable.vue";
import type { DataTableColumn } from "@/components/common/DataTable.vue";
import EmptyState from "@/components/common/EmptyState.vue";
import LoadingState from "@/components/common/LoadingState.vue";
import PageHeader from "@/components/common/PageHeader.vue";
import Pagination from "@/components/common/Pagination.vue";
import TablePageLayout from "@/components/layout/TablePageLayout.vue";
import { useForm } from "@/composables/useForm";
import { useTableLoader } from "@/composables/useTableLoader";
import { mergeProviderRow, normalizeProviderConfig, normalizeProviderProfilePayload, normalizeProviderProfiles, normalizeProviderValidation, orderProviderProfiles, validationComplete, type ProviderConfigView, type ProviderProfileRow, type ProviderValidationView } from "@/stores/provider-profiles-view";
import type { ApiError, ErrorDiagnostic, ProviderProfile } from "@/types";

const columns: DataTableColumn[] = [
  { key: "profile", label: "Profile" },
  { key: "configured", label: "状态" },
  { key: "secret", label: "SecretRef" },
  { key: "hash", label: "Fingerprint" },
  { key: "bridge", label: "Bridge" },
  { key: "validation", label: "Validation" },
  { key: "actions", label: "操作", align: "right" }
];

const table = useTableLoader<ProviderProfileRow>(loadProfiles);
const selectedProfile = ref<ProviderProfileRow | null>(null);
const credentialDialogOpen = ref(false);
const configDialogOpen = ref(false);
const removeDialogOpen = ref(false);
const apiKeyInput = ref("");
const configText = ref("");
const configInfo = ref<ProviderConfigView | null>(null);
const validation = ref<ProviderValidationView | null>(null);
const validationError = ref<string | null>(null);
const validationApiError = ref<ApiError | null>(null);
const validationDiagnostic = ref<ErrorDiagnostic | null>(null);
const validatingProfile = ref<string | null>(null);
const credentialForm = useForm();
const configForm = useForm();
const removeForm = useForm();
const page = ref(1);
const pageSize = 10;

const rows = computed(() => orderProviderProfiles(table.rows.value));
const pageRows = computed(() => rows.value.slice((page.value - 1) * pageSize, page.value * pageSize));

onMounted(() => void table.reload());

async function loadProfiles(): Promise<ProviderProfileRow[]> {
  const response = await providerProfilesAPI.list();
  if (!response.ok) throw response;
  return normalizeProviderProfiles(response.data);
}

function rowKey(row: ProviderProfileRow): string {
  return row.profile;
}

function openCredential(row: ProviderProfileRow): void {
  selectedProfile.value = row;
  apiKeyInput.value = "";
  credentialDialogOpen.value = true;
}

function openRemove(row: ProviderProfileRow): void {
  selectedProfile.value = row;
  removeDialogOpen.value = true;
  removeForm.error.value = null;
}

async function saveCredential(): Promise<void> {
  const row = selectedProfile.value;
  if (!row || !apiKeyInput.value.trim()) return;
  const ok = await credentialForm.submit(async () => {
    const response = await providerProfilesAPI.setKey(row.profile, apiKeyInput.value);
    if (!response.ok) throw response;
    table.rows.value = mergeProviderRow(table.rows.value, normalizeProviderProfilePayload(response.data));
  }, "Credential updated");
  if (ok) {
    apiKeyInput.value = "";
    credentialDialogOpen.value = false;
  }
}

async function openConfig(row: ProviderProfileRow): Promise<void> {
  selectedProfile.value = row;
  configDialogOpen.value = true;
  configForm.error.value = null;
  configForm.apiError.value = null;
  configForm.diagnostic.value = null;
  configInfo.value = null;
  configText.value = "";
  const response = await providerProfilesAPI.config(row.profile);
  if (!response.ok) {
    configForm.error.value = response.error ?? `HTTP ${response.status}`;
    configForm.apiError.value = response.apiError ?? null;
    configForm.diagnostic.value = response.diagnostic ?? null;
    return;
  }
  const config = normalizeProviderConfig(response.data, row.profile);
  configInfo.value = config;
  configText.value = config.configToml;
}

async function saveConfig(): Promise<void> {
  const row = selectedProfile.value;
  if (!row) return;
  const ok = await configForm.submit(async () => {
    const response = await providerProfilesAPI.setConfig(row.profile, configText.value);
    if (!response.ok) throw response;
    table.rows.value = mergeProviderRow(table.rows.value, normalizeProviderProfilePayload(response.data));
  }, "Config updated");
  if (ok) configDialogOpen.value = false;
}

async function removeProfile(): Promise<void> {
  const row = selectedProfile.value;
  if (!row) return;
  const ok = await removeForm.submit(async () => {
    const response = await providerProfilesAPI.remove(row.profile);
    if (!response.ok) throw response;
    table.rows.value = table.rows.value.filter((item) => item.profile !== row.profile);
  }, "Profile removed");
  if (ok) {
    removeDialogOpen.value = false;
    selectedProfile.value = null;
  }
}

async function validateProfile(row: ProviderProfileRow): Promise<void> {
  validatingProfile.value = row.profile;
  validationError.value = null;
  validationApiError.value = null;
  validationDiagnostic.value = null;
  validation.value = null;
  const submit = await providerProfilesAPI.validate(row.profile);
  if (!submit.ok) {
    validationError.value = submit.error ?? `HTTP ${submit.status}`;
    validationApiError.value = submit.apiError ?? null;
    validationDiagnostic.value = submit.diagnostic ?? null;
    validatingProfile.value = null;
    return;
  }
  let current = normalizeProviderValidation(submit.data, row.profile);
  validation.value = current;
  const validationId = current.validationId;
  for (let attempt = 0; validationId && attempt < 30 && !validationComplete(current.status); attempt += 1) {
    await delay(2000);
    const poll = await providerProfilesAPI.validation(row.profile, validationId);
    if (!poll.ok) {
      validationError.value = poll.error ?? `HTTP ${poll.status}`;
      validationApiError.value = poll.apiError ?? null;
      validationDiagnostic.value = poll.diagnostic ?? null;
      break;
    }
    current = normalizeProviderValidation(poll.data, row.profile);
    validation.value = current;
  }
  validatingProfile.value = null;
  void table.reload();
}

function delay(ms: number): Promise<void> {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

function displayDate(value: string): string {
  if (!value) return "-";
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return value;
  return date.toLocaleString("zh-CN", { month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" });
}
</script>

<template>
  <section class="route-stack provider-admin-page">
    <PageHeader eyebrow="Admin" title="Provider Profiles" description="Provider credential/config 由 Cloud API 鉴权后委托 AgentRun；页面只显示 SecretRef、fingerprint 和 validation 摘要。" />
    <LoadingState v-if="table.loading.value && !rows.length" />
    <section v-else-if="table.error.value" class="data-panel admin-crud-panel">
      <EmptyState title="Provider Profiles 加载失败" :description="table.error.value" :api-error="table.apiError.value" :diagnostic="table.diagnostic.value" action-label="重试" @action="table.reload" />
      <p class="muted-box">当前错误会保留为委托链路状态，不再用 raw JSON dump 作为页面主体。</p>
    </section>
    <TablePageLayout v-else title="Profiles" subtitle="AgentRun provider profile registry">
      <template #actions>
        <button class="table-action" type="button" :disabled="table.loading.value" @click="table.reload">刷新</button>
      </template>
      <DataTable :columns="columns" :rows="pageRows" :row-key="rowKey" empty-text="暂无 provider profile。">
        <template #cell-profile="{ row }">
          <strong>{{ (row as ProviderProfileRow).profile }}</strong>
          <small>{{ displayDate((row as ProviderProfileRow).updatedAt) }}</small>
        </template>
        <template #cell-configured="{ row }">
          <span class="status-pill" :data-status="(row as ProviderProfileRow).configured ? 'active' : 'disabled'">{{ (row as ProviderProfileRow).configured ? "configured" : "missing" }}</span>
        </template>
        <template #cell-secret="{ row }">
          <code>{{ (row as ProviderProfileRow).secretRefText }}</code>
          <small>{{ (row as ProviderProfileRow).resourceVersion || "rv -" }}</small>
        </template>
        <template #cell-hash="{ row }">
          <span>key {{ (row as ProviderProfileRow).credentialHashSuffix || "-" }}</span>
          <small>config {{ (row as ProviderProfileRow).configHashSuffix || "-" }}</small>
        </template>
        <template #cell-bridge="{ row }">
          {{ (row as ProviderProfileRow).bridgeText || "-" }}
        </template>
        <template #cell-validation="{ row }">
          <span class="status-pill" :data-status="(row as ProviderProfileRow).validationStatus || 'pending'">{{ (row as ProviderProfileRow).validationStatus || "not run" }}</span>
          <small v-if="(row as ProviderProfileRow).failureKind">{{ (row as ProviderProfileRow).failureKind }}</small>
        </template>
        <template #cell-actions="{ row }">
          <div class="table-actions-inline">
            <button class="table-action" type="button" @click="openCredential(row as ProviderProfileRow)">Key</button>
            <button class="table-action" type="button" @click="openConfig(row as ProviderProfileRow)">Config</button>
            <button class="table-action" type="button" :disabled="validatingProfile !== null" @click="validateProfile(row as ProviderProfileRow)">{{ validatingProfile === (row as ProviderProfileRow).profile ? "验证中" : "Validate" }}</button>
            <button class="table-action danger" type="button" @click="openRemove(row as ProviderProfileRow)">Remove</button>
          </div>
        </template>
      </DataTable>
      <template #pagination>
        <Pagination v-model:page="page" :page-size="pageSize" :total="rows.length" />
      </template>
    </TablePageLayout>

    <section id="provider-validation-summary" class="data-panel admin-crud-panel provider-validation-panel">
      <header class="panel-header">
        <h2>Validation</h2>
        <span class="status-pill" :data-status="validation?.status || (validationError ? 'failed' : 'pending')">{{ validation?.status || (validationError ? "failed" : "idle") }}</span>
      </header>
      <ApiErrorDiagnostic v-if="validationError" :error="validationError" :api-error="validationApiError" :diagnostic="validationDiagnostic" compact />
      <dl v-if="validation" class="field-grid">
        <div><dt>validationId</dt><dd>{{ validation.validationId || "-" }}</dd></div>
        <div><dt>runId</dt><dd>{{ validation.runId || "-" }}</dd></div>
        <div><dt>commandId</dt><dd>{{ validation.commandId || "-" }}</dd></div>
        <div><dt>jobName</dt><dd>{{ validation.jobName || "-" }}</dd></div>
        <div><dt>traceId</dt><dd>{{ validation.traceId || "-" }}</dd></div>
        <div><dt>failureKind</dt><dd>{{ validation.failureKind || validation.terminalStatus || "-" }}</dd></div>
      </dl>
      <p v-else-if="!validationError" class="muted-box">尚未触发本页 validate workflow。</p>
    </section>

    <BaseDialog :open="credentialDialogOpen" title="Provider Credential" :description="selectedProfile?.profile || ''" @close="credentialDialogOpen = false">
      <form class="admin-form" @submit.prevent="saveCredential">
        <label>
          <span>API key</span>
          <input id="provider-api-key-input" v-model="apiKeyInput" type="password" autocomplete="off" placeholder="输入后只用于本次提交">
        </label>
        <ApiErrorDiagnostic v-if="credentialForm.error.value" :error="credentialForm.error.value" :api-error="credentialForm.apiError.value" :diagnostic="credentialForm.diagnostic.value" compact />
        <p v-if="credentialForm.notice.value" class="form-notice">{{ credentialForm.notice.value }}</p>
      </form>
      <template #footer>
        <button class="table-action" type="button" :disabled="credentialForm.loading.value" @click="credentialDialogOpen = false">取消</button>
        <button class="table-action" type="button" :disabled="credentialForm.loading.value || !apiKeyInput.trim()" @click="saveCredential">{{ credentialForm.loading.value ? "保存中" : "保存" }}</button>
      </template>
    </BaseDialog>

    <BaseDialog :open="configDialogOpen" title="Provider config.toml" :description="selectedProfile?.profile || ''" wide @close="configDialogOpen = false">
      <form class="admin-form" @submit.prevent="saveConfig">
        <label>
          <span>config.toml</span>
          <textarea id="provider-config-toml" v-model="configText" rows="14" spellcheck="false" />
        </label>
        <p v-if="configInfo" class="muted-box">config fingerprint: {{ configInfo.configHashSuffix || "-" }} / valuesPrinted={{ configInfo.valuesPrinted ? "true" : "false" }}</p>
        <ApiErrorDiagnostic v-if="configForm.error.value" :error="configForm.error.value" :api-error="configForm.apiError.value" :diagnostic="configForm.diagnostic.value" compact />
        <p v-if="configForm.notice.value" class="form-notice">{{ configForm.notice.value }}</p>
      </form>
      <template #footer>
        <button class="table-action" type="button" :disabled="configForm.loading.value" @click="configDialogOpen = false">取消</button>
        <button class="table-action" type="button" :disabled="configForm.loading.value" @click="saveConfig">{{ configForm.loading.value ? "保存中" : "保存" }}</button>
      </template>
    </BaseDialog>

    <ConfirmDialog :open="removeDialogOpen" title="Remove provider profile" :message="`删除 ${selectedProfile?.profile || 'profile'} 的管理配置；内建能力仍由后端决定是否保留。`" confirm-label="删除" :pending="removeForm.loading.value" @close="removeDialogOpen = false" @confirm="removeProfile" />
    <ApiErrorDiagnostic v-if="removeForm.error.value" class="admin-action-error" :error="removeForm.error.value" :api-error="removeForm.apiError.value" :diagnostic="removeForm.diagnostic.value" compact />
  </section>
</template>
