<template>
  <h2 class="ops-page-title">订阅包审批</h2>

  <div class="ops-card">
    <div class="ops-toolbar kol-subscriptions-toolbar">
      <a-input
        v-model:value="filter.keyword"
        class="kol-subscriptions-search"
        placeholder="搜索租户 / 手机号 / KOL / 模板包 / ID"
        allow-clear
        @press-enter="reload"
        @change="onKeywordChange"
      />
      <a-select
        v-model:value="filter.status"
        class="kol-subscriptions-status"
        :options="statusOptions"
        placeholder="订阅状态"
        allow-clear
        @change="reload"
      />
      <a-button @click="reload">刷新</a-button>
      <span class="kol-subscriptions-toolbar__spacer" />
      <a-tag color="orange">待审批 {{ pendingRowsCount }}</a-tag>
      <a-tag>当前筛选 {{ total }}</a-tag>
      <a-button type="primary" @click="openManualBind">
        <template #icon><PlusOutlined /></template>
        绑定模板包
      </a-button>
    </div>

    <a-table
      :columns="columns"
      :data-source="rows"
      :loading="loading"
      :pagination="pagination"
      row-key="id"
      @change="onTableChange"
    >
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'subscriber'">
          <div class="primary-cell">
            <strong>{{ record.tenant_name }}</strong>
            <span>
              {{ record.subscriber_phone ? `手机 ${record.subscriber_phone}` : "手机号 —" }}
              · 租户 #{{ record.tenant_id }} · 申请 #{{ record.id }}
            </span>
          </div>
        </template>
        <template v-else-if="column.key === 'package'">
          <div class="primary-cell">
            <strong>{{ record.package_name }}</strong>
            <span>包 #{{ record.package_id }}</span>
          </div>
        </template>
        <template v-else-if="column.key === 'creator'">
          <div class="creator-cell">
            <a-avatar :src="record.kol_avatar_url || undefined" size="small">
              {{ record.kol_display_name.charAt(0) || "K" }}
            </a-avatar>
            <div class="primary-cell">
              <strong>{{ record.kol_display_name }}</strong>
              <span>{{ record.creator_tenant_name }} · 租户 #{{ record.creator_tenant_id }}</span>
            </div>
          </div>
        </template>
        <template v-else-if="column.key === 'status'">
          <a-space direction="vertical" :size="4">
            <a-tag :color="statusColor(record.status)">
              {{ statusLabel(record.status) }}
            </a-tag>
            <a-tag :color="record.package_status === 'published' ? 'green' : 'default'">
              包：{{ packageStatusLabel(record.package_status) }}
            </a-tag>
          </a-space>
        </template>
        <template v-else-if="column.key === 'prompts'">
          <div class="prompt-count">
            <strong>{{ record.access_prompt_count }}</strong>
            <span>/ {{ record.prompt_count }} 个 Prompt</span>
          </div>
        </template>
        <template v-else-if="column.key === 'period'">
          <div class="period-cell">
            <span>开始：{{ formatOptionalDate(record.start_at) }}</span>
            <span>到期：{{ formatOptionalDate(record.end_at, "永不过期") }}</span>
          </div>
        </template>
        <template v-else-if="column.key === 'created_at'">
          {{ formatDate(record.created_at) }}
        </template>
        <template v-else-if="column.key === 'actions'">
          <div class="table-actions-row">
            <a-tooltip v-if="record.status === 'pending'" title="通过">
              <a-button
                type="text"
                shape="circle"
                size="small"
                class="action-btn action-approve"
                @click="openApprove(record)"
              >
                <CheckOutlined />
              </a-button>
            </a-tooltip>

            <a-tooltip v-if="record.status === 'pending' || record.status === 'active'" title="撤销订阅">
              <a-popconfirm
                title="确认撤销该订阅？撤销后订阅方将无法使用包内 Prompt。"
                :ok-button-props="{ danger: true, loading: revokeLoadingId === record.id }"
                @confirm="revoke(record)"
              >
                <a-button
                  type="text"
                  shape="circle"
                  size="small"
                  class="action-btn action-revoke"
                >
                  <StopOutlined />
                </a-button>
              </a-popconfirm>
            </a-tooltip>
            <span v-if="record.status !== 'pending' && record.status !== 'active'" class="muted-text">无操作</span>
          </div>
        </template>
      </template>
    </a-table>
  </div>

  <a-modal
    v-model:open="approveOpen"
    :title="approveTarget ? `通过订阅申请 #${approveTarget.id}` : '通过订阅申请'"
    :confirm-loading="approveLoading"
    ok-text="通过"
    @ok="submitApprove"
    @cancel="approveOpen = false"
  >
    <a-alert
      v-if="approveTarget"
      class="approve-alert"
      type="info"
      show-icon
      :message="`${approveTarget.tenant_name} 将获得「${approveTarget.package_name}」的使用权限`"
    />
    <a-form layout="vertical" :model="approveForm">
      <a-form-item label="订阅有效期" help="留空表示不过期；过渡期可先用人工控制。">
        <a-date-picker
          v-model:value="approveForm.end_date"
          class="approve-date-picker"
          format="YYYY-MM-DD"
          value-format="YYYY-MM-DD"
          allow-clear
          placeholder="永不过期"
        />
      </a-form-item>
    </a-form>
  </a-modal>

  <a-modal
    v-model:open="manualBindOpen"
    title="手动绑定精调模板包"
    :confirm-loading="manualBindLoading"
    ok-text="绑定"
    @ok="submitManualBind"
    @cancel="manualBindOpen = false"
  >
    <a-alert
      class="manual-bind-alert"
      type="info"
      show-icon
      message="输入用户手机号并选择精调模板市场的模板包，保存后会直接发放包内 Prompt 使用权限。"
    />
    <a-form layout="vertical" :model="manualBindForm">
      <a-form-item label="用户手机号" required>
        <a-input
          v-model:value="manualBindForm.phone"
          placeholder="13800138000"
          allow-clear
          @press-enter="submitManualBind"
        />
      </a-form-item>
      <a-form-item label="精调模板包" required>
        <a-select
          v-model:value="manualBindForm.package_id"
          show-search
          allow-clear
          :filter-option="false"
          :loading="packageLoading"
          :options="packageOptions"
          placeholder="搜索模板包 / KOL / 包 ID"
          @focus="loadPackages()"
          @search="onPackageSearch"
        />
      </a-form-item>
      <div v-if="selectedPackage" class="manual-bind-preview">
        <div class="creator-cell">
          <a-avatar :src="selectedPackage.kol_avatar_url || undefined" size="small">
            {{ selectedPackage.kol_display_name.charAt(0) || "K" }}
          </a-avatar>
          <div class="primary-cell">
            <strong>{{ selectedPackage.name }}</strong>
            <span>{{ selectedPackage.kol_display_name }} · {{ selectedPackage.creator_tenant_name }}</span>
          </div>
        </div>
        <a-tag color="blue">{{ selectedPackage.prompt_count }} 个 Prompt</a-tag>
      </div>
      <a-form-item label="授权有效期" help="留空表示不过期；如果该用户已有待审批/已通过记录，会更新为这里选择的有效期。">
        <a-date-picker
          v-model:value="manualBindForm.end_date"
          class="approve-date-picker"
          format="YYYY-MM-DD"
          value-format="YYYY-MM-DD"
          allow-clear
          placeholder="永不过期"
        />
      </a-form-item>
    </a-form>
  </a-modal>
</template>

<script setup lang="ts">
import { PlusOutlined, CheckOutlined, StopOutlined } from "@ant-design/icons-vue";
import type { TableColumnsType, TablePaginationConfig } from "ant-design-vue";
import { message } from "ant-design-vue";
import dayjs from "dayjs";
import { computed, onMounted, reactive, ref } from "vue";

import { OpsApiError, http } from "@/lib/http";

interface KolSubscriptionRow {
  id: number;
  tenant_id: number;
  tenant_name: string;
  subscriber_name: string | null;
  subscriber_phone: string | null;
  package_id: number;
  package_name: string;
  package_status: string;
  creator_tenant_id: number;
  creator_tenant_name: string;
  kol_profile_id: number;
  kol_display_name: string;
  kol_avatar_url: string | null;
  status: string;
  prompt_count: number;
  access_prompt_count: number;
  start_at: string | null;
  end_at: string | null;
  created_at: string;
  updated_at: string;
}

interface ListResult {
  items: KolSubscriptionRow[];
  total: number;
  page: number;
  size: number;
}

interface KolPackageOption {
  id: number;
  name: string;
  status: string;
  creator_tenant_id: number;
  creator_tenant_name: string;
  kol_profile_id: number;
  kol_display_name: string;
  kol_avatar_url: string | null;
  prompt_count: number;
  created_at: string;
  updated_at: string;
}

const filter = reactive({
  keyword: "",
  status: "pending" as string | undefined,
});

const statusOptions = [
  { label: "审核中", value: "pending" },
  { label: "已通过", value: "active" },
  { label: "已撤销", value: "revoked" },
  { label: "已过期", value: "expired" },
];

const columns: TableColumnsType<KolSubscriptionRow> = [
  { title: "申请租户", key: "subscriber", width: 220 },
  { title: "订阅包", key: "package", width: 220 },
  { title: "KOL", key: "creator", width: 260 },
  { title: "状态", key: "status", width: 130 },
  { title: "授权 Prompt", key: "prompts", width: 130 },
  { title: "有效期", key: "period", width: 210 },
  { title: "申请时间", key: "created_at", width: 180 },
  { title: "操作", key: "actions", width: 120 },
];

const rows = ref<KolSubscriptionRow[]>([]);
const packageRows = ref<KolPackageOption[]>([]);
const loading = ref(false);
const packageLoading = ref(false);
const page = ref(1);
const size = ref(20);
const total = ref(0);

const pagination = computed<TablePaginationConfig>(() => ({
  current: page.value,
  pageSize: size.value,
  total: total.value,
  showSizeChanger: true,
  pageSizeOptions: ["10", "20", "50", "100"],
}));

const pendingRowsCount = computed(() => rows.value.filter((row) => row.status === "pending").length);

const packageOptions = computed(() =>
  packageRows.value.map((item) => ({
    label: `${item.name} · ${item.kol_display_name} · ${item.prompt_count} 个 Prompt`,
    value: item.id,
  })),
);

let keywordTimer: number | null = null;
let packageSearchTimer: number | null = null;

function onKeywordChange() {
  if (keywordTimer) window.clearTimeout(keywordTimer);
  keywordTimer = window.setTimeout(() => {
    page.value = 1;
    void reload();
  }, 300);
}

async function reload() {
  loading.value = true;
  try {
    const result = await http.get<ListResult>("/kol/subscriptions", {
      keyword: filter.keyword || undefined,
      status: filter.status || undefined,
      page: page.value,
      size: size.value,
    });
    rows.value = result.items;
    total.value = result.total;
  } catch (error) {
    if (error instanceof OpsApiError) message.error(error.detail || error.message);
  } finally {
    loading.value = false;
  }
}

async function loadPackages(keyword = "") {
  packageLoading.value = true;
  try {
    packageRows.value = await http.get<KolPackageOption[]>("/kol/packages", {
      keyword: keyword || undefined,
      size: 50,
    });
  } catch (error) {
    if (error instanceof OpsApiError) message.error(error.detail || error.message);
  } finally {
    packageLoading.value = false;
  }
}

function onPackageSearch(value: string) {
  if (packageSearchTimer) window.clearTimeout(packageSearchTimer);
  packageSearchTimer = window.setTimeout(() => {
    void loadPackages(value.trim());
  }, 300);
}

function onTableChange(pag: TablePaginationConfig) {
  page.value = pag.current ?? 1;
  size.value = pag.pageSize ?? 20;
  void reload();
}

const manualBindOpen = ref(false);
const manualBindLoading = ref(false);
const manualBindForm = reactive({
  phone: "",
  package_id: undefined as number | undefined,
  end_date: undefined as string | undefined,
});

const selectedPackage = computed(() =>
  packageRows.value.find((item) => item.id === manualBindForm.package_id) ?? null,
);

function resetManualBind() {
  manualBindForm.phone = "";
  manualBindForm.package_id = undefined;
  manualBindForm.end_date = undefined;
}

function openManualBind() {
  resetManualBind();
  manualBindOpen.value = true;
  void loadPackages();
}

async function submitManualBind() {
  const phone = normalizePhone(manualBindForm.phone);
  if (!phone) {
    message.warning("请输入有效手机号");
    return;
  }
  if (!manualBindForm.package_id) {
    message.warning("请选择精调模板包");
    return;
  }
  if (manualBindForm.end_date && dayjs(manualBindForm.end_date).endOf("day").isBefore(dayjs())) {
    message.warning("有效期不能早于今天");
    return;
  }

  manualBindLoading.value = true;
  try {
    const result = await http.post<KolSubscriptionRow>("/kol/subscriptions/manual-bind", {
      phone,
      package_id: manualBindForm.package_id,
      end_at: manualBindForm.end_date ? dayjs(manualBindForm.end_date).endOf("day").toISOString() : null,
    });
    message.success(`已为 ${phone} 绑定「${result.package_name}」`);
    manualBindOpen.value = false;
    filter.keyword = phone;
    filter.status = "active";
    page.value = 1;
    void reload();
  } catch (error) {
    if (error instanceof OpsApiError) message.error(error.detail || error.message);
  } finally {
    manualBindLoading.value = false;
  }
}

const approveOpen = ref(false);
const approveLoading = ref(false);
const approveTarget = ref<KolSubscriptionRow | null>(null);
const approveForm = reactive({
  end_date: undefined as string | undefined,
});

function openApprove(row: KolSubscriptionRow) {
  approveTarget.value = row;
  approveForm.end_date = undefined;
  approveOpen.value = true;
}

async function submitApprove() {
  if (!approveTarget.value) return;
  if (approveForm.end_date && dayjs(approveForm.end_date).endOf("day").isBefore(dayjs())) {
    message.warning("有效期不能早于今天");
    return;
  }

  approveLoading.value = true;
  try {
    await http.post<KolSubscriptionRow>(`/kol/subscriptions/${approveTarget.value.id}/approve`, {
      end_at: approveForm.end_date ? dayjs(approveForm.end_date).endOf("day").toISOString() : null,
    });
    message.success("订阅已通过，Prompt 权限已发放");
    approveOpen.value = false;
    void reload();
  } catch (error) {
    if (error instanceof OpsApiError) message.error(error.detail || error.message);
  } finally {
    approveLoading.value = false;
  }
}

const revokeLoadingId = ref<number | null>(null);

async function revoke(row: KolSubscriptionRow) {
  revokeLoadingId.value = row.id;
  try {
    await http.post<KolSubscriptionRow>(`/kol/subscriptions/${row.id}/revoke`);
    message.success("订阅已撤销");
    void reload();
  } catch (error) {
    if (error instanceof OpsApiError) message.error(error.detail || error.message);
  } finally {
    revokeLoadingId.value = null;
  }
}

function statusLabel(status: string): string {
  if (status === "pending") return "审核中";
  if (status === "active") return "已通过";
  if (status === "revoked") return "已撤销";
  if (status === "expired") return "已过期";
  return status;
}

function statusColor(status: string): string {
  if (status === "pending") return "orange";
  if (status === "active") return "green";
  if (status === "revoked") return "red";
  if (status === "expired") return "default";
  return "default";
}

function packageStatusLabel(status: string): string {
  if (status === "published") return "已发布";
  if (status === "draft") return "草稿";
  if (status === "archived") return "已归档";
  return status;
}

function normalizePhone(value: string): string {
  const phone = value.trim().replace(/[\s-]/g, "");
  return /^\+?\d{6,20}$/.test(phone) ? phone : "";
}

function formatOptionalDate(value: string | null, empty = "—"): string {
  if (!value) return empty;
  return dayjs(value).format("YYYY-MM-DD");
}

function formatDate(value: string): string {
  return dayjs(value).format("YYYY-MM-DD HH:mm:ss");
}

onMounted(() => {
  void reload();
});
</script>

<style scoped>
.kol-subscriptions-toolbar {
  align-items: center;
}

.kol-subscriptions-search {
  width: 320px;
}

.kol-subscriptions-status {
  width: 140px;
}

.kol-subscriptions-toolbar__spacer {
  flex: 1;
}

.primary-cell {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.primary-cell strong {
  color: #0f172a;
  font-weight: 650;
}

.primary-cell span,
.muted-text {
  color: #94a3b8;
  font-size: 12px;
}

.creator-cell {
  display: flex;
  gap: 10px;
  align-items: center;
}

.prompt-count {
  display: flex;
  align-items: baseline;
  gap: 4px;
}

.prompt-count strong {
  color: #0f172a;
  font-size: 18px;
}

.prompt-count span {
  color: #64748b;
  font-size: 12px;
}

.period-cell {
  display: flex;
  flex-direction: column;
  gap: 4px;
  color: #64748b;
  font-size: 12px;
}

.danger-link {
  color: #dc2626;
}

.approve-alert {
  margin-bottom: 16px;
}

.manual-bind-alert {
  margin-bottom: 16px;
}

.manual-bind-preview {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: -2px 0 16px;
  padding: 12px;
  border: 1px solid #dbeafe;
  border-radius: 8px;
  background: #f8fbff;
}

.approve-date-picker {
  width: 100%;
}
</style>
