<script setup lang="ts">
import { computed, onMounted, reactive, ref, watch } from 'vue';
import { ElMessage } from 'element-plus';
import { useRoute } from 'vue-router';
import readXlsxFile from 'read-excel-file/browser';
import { http, type PageResult } from '../api/http';

type UserOrganizationRow = {
  userId: number;
  username: string;
  email: string;
  phone?: string;
  status: number;
  lastLoginAt?: string;
  tenantId: number;
  tenantName: string;
  tenantSlug: string;
  tenantPlan: string;
  tenantStatus: number;
  memberId?: number;
  accountRole?: string;
  memberRole?: string;
  position?: string;
  joinedAt?: string;
  maxMembers?: number;
  maxProjects?: number;
  maxConcurrentTasks?: number;
  permissionScope?: string;
  dataBoundary?: string;
};

type TenantOption = {
  id: number;
  name: string;
  slug: string;
  plan: string;
  status: number;
};

const query = reactive({ keyword: '', tenantId: '', status: undefined as number | undefined, page: 1, size: 20 });
const page = ref<PageResult<UserOrganizationRow>>({ records: [], total: 0, page: 1, size: 20 });
const pageSizes = [10, 20, 30];
const route = useRoute();
const detailRow = ref<UserOrganizationRow | null>(null);
const tenants = ref<TenantOption[]>([]);
const memberDialog = ref(false);
const importDialog = ref(false);
const importing = ref(false);
const importRows = ref<any[]>([]);
const importResults = ref<any[]>([]);
const memberForm = reactive({
  tenantId: undefined as number | undefined,
  username: '',
  email: '',
  phone: '',
  password: '',
  role: 'member',
  position: '',
  status: 1,
});
const detailVisible = computed({
  get: () => Boolean(detailRow.value),
  set: (value: boolean) => {
    if (!value) detailRow.value = null;
  },
});
const importValidRows = computed(() => importRows.value.filter((row) => !row.error));
const importSuccessCount = computed(() => importResults.value.filter((row) => row.success).length);
const importFailCount = computed(() => importResults.value.filter((row) => !row.success).length);

const hierarchy = [
  {
    title: '平台层',
    subtitle: '运营账号 / 后台菜单权限',
    points: ['平台管理员按角色访问运营菜单', '超级管理员拥有全局配置与审计权限', '运营、财务和只读账号只处理授权模块']
  },
  {
    title: '企业租户层',
    subtitle: '企业主体 / 套餐配额',
    points: ['租户编号是业务数据隔离边界', '套餐决定成员、项目、并发和积分额度', '暂停、恢复、模拟登录均记录审计日志']
  },
  {
    title: '组织员工层',
    subtitle: '员工账号 / 成员关系',
    points: ['员工账号必须归属一个企业租户', '所有者、管理员、成员决定组织内权限', '所有项目、素材、账务默认只在租户内可见']
  }
];

function roleLabel(role?: string) {
  const map: Record<string, string> = { owner: '所有者', admin: '管理员', member: '成员' };
  return role ? map[role] || role : '未绑定';
}

function normalizeImportRole(value?: string) {
  const role = String(value || '').trim().toLowerCase();
  const map: Record<string, string> = {
    owner: 'owner',
    admin: 'admin',
    member: 'member',
    所有者: 'owner',
    管理员: 'admin',
    成员: 'member',
  };
  return map[role] || 'member';
}

function normalizeImportStatus(value?: string) {
  const status = String(value || '').trim();
  if (['0', '禁用', '停用'].includes(status)) return 0;
  return 1;
}

function statusType(status?: number) {
  return status === 1 ? 'success' : 'info';
}

function statusLabel(status?: number) {
  return status === 1 ? '正常' : '禁用';
}

function planLabel(plan?: string) {
  const map: Record<string, string> = { free: '免费版', pro: '专业版', team: '团队版', enterprise: '企业版' };
  const key = String(plan || '').toLowerCase();
  return map[key] || plan || '未配置套餐';
}

function formatTime(value?: string) {
  if (!value) return '-';
  return value.replace('T', ' ').slice(0, 19);
}

function tenantLabel(row: TenantOption) {
  return `${row.name}（ID ${row.id}）`;
}

async function load() {
  page.value = await http.get('/users', { params: query });
}

async function loadTenants() {
  const res = await http.get<PageResult<TenantOption>>('/tenants', { params: { page: 1, size: 100 } });
  tenants.value = res.records || [];
}

function applyRouteQuery() {
  query.keyword = String(route.query.keyword || '');
  query.tenantId = String(route.query.tenantId || '');
  query.status = route.query.status === undefined ? undefined : Number(route.query.status);
  query.page = 1;
}

function search() {
  query.page = 1;
  load();
}

function resetMemberForm() {
  memberForm.tenantId = query.tenantId ? Number(query.tenantId) : undefined;
  memberForm.username = '';
  memberForm.email = '';
  memberForm.phone = '';
  memberForm.password = '';
  memberForm.role = 'member';
  memberForm.position = '';
  memberForm.status = 1;
}

function openCreateMember() {
  resetMemberForm();
  memberDialog.value = true;
}

async function saveMember() {
  if (!memberForm.tenantId) {
    ElMessage.warning('请选择企业租户');
    return;
  }
  if (!memberForm.username || !memberForm.email) {
    ElMessage.warning('员工账号和邮箱必填');
    return;
  }
  await http.post(`/tenants/${memberForm.tenantId}/members`, {
    username: memberForm.username,
    email: memberForm.email,
    phone: memberForm.phone,
    password: memberForm.password,
    role: memberForm.role,
    position: memberForm.position,
    status: memberForm.status,
  });
  ElMessage.success('员工已新增到组织关系');
  memberDialog.value = false;
  await load();
}

function stableDownloadCsv(filename: string, rows: string[][]) {
  const csv = rows.map((line) => line.map((cell) => `"${String(cell).replace(/"/g, '""')}"`).join(',')).join('\n');
  const blob = new Blob([`\uFEFF${csv}`], { type: 'text/csv;charset=utf-8;' });
  const url = URL.createObjectURL(blob);
  const link = document.createElement('a');
  link.href = url;
  link.download = filename;
  link.style.display = 'none';
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
  window.setTimeout(() => URL.revokeObjectURL(url), 1000);
}

function downloadImportTemplate() {
  stableDownloadCsv('组织员工批量导入模板.csv', [
    ['企业租户ID', '用户名', '邮箱', '手机号', '组织角色', '岗位', '初始密码', '状态'],
    ['1001', 'zhangsan_editor', 'zhangsan@example.com', '13800000001', '成员', '短剧制作', 'Dramix@123', '正常'],
    ['1001', 'lisi_admin', 'lisi@example.com', '13800000002', '管理员', '项目负责人', 'Dramix@123', '正常'],
  ]);
}

function splitDelimitedLine(line: string, delimiter: string) {
  if (delimiter === '\t') return line.split('\t').map((cell) => cell.trim());
  const cells: string[] = [];
  let current = '';
  let quoted = false;
  for (let index = 0; index < line.length; index += 1) {
    const char = line[index];
    if (char === '"') {
      if (quoted && line[index + 1] === '"') {
        current += '"';
        index += 1;
      } else {
        quoted = !quoted;
      }
    } else if (char === ',' && !quoted) {
      cells.push(current.trim());
      current = '';
    } else {
      current += char;
    }
  }
  cells.push(current.trim());
  return cells;
}

function buildImportRows(rows: string[][]) {
  const cleanedRows = rows
    .map((line) => line.map((cell) => String(cell || '').trim()))
    .filter((line) => line.some(Boolean));
  if (cleanedRows.length < 2) {
    ElMessage.warning('表格至少需要表头和一行员工数据');
    return [];
  }
  const headerAlias: Record<string, string> = {
    企业租户id: 'tenantId',
    租户id: 'tenantId',
    tenantid: 'tenantId',
    企业编号: 'tenantId',
    用户名: 'username',
    username: 'username',
    账号: 'username',
    邮箱: 'email',
    email: 'email',
    手机号: 'phone',
    phone: 'phone',
    组织角色: 'role',
    角色: 'role',
    role: 'role',
    岗位: 'position',
    position: 'position',
    初始密码: 'password',
    密码: 'password',
    password: 'password',
    状态: 'status',
    status: 'status',
  };
  const headerProps = cleanedRows[0].map((header) => headerAlias[header.replace(/\s/g, '').toLowerCase()] || header);
  return cleanedRows.slice(1).map((cells, index) => {
    const raw: Record<string, string> = {};
    headerProps.forEach((prop, cellIndex) => {
      raw[prop] = cells[cellIndex] || '';
    });
    const tenantId = Number(raw.tenantId || 0);
    const role = normalizeImportRole(raw.role);
    const row = {
      rowNumber: index + 2,
      tenantId,
      tenantName: tenants.value.find((tenant) => tenant.id === tenantId)?.name || '',
      username: raw.username?.trim(),
      email: raw.email?.trim(),
      phone: raw.phone?.trim(),
      role,
      roleLabel: roleLabel(role),
      position: raw.position?.trim(),
      password: raw.password?.trim(),
      status: normalizeImportStatus(raw.status),
      statusLabel: normalizeImportStatus(raw.status) === 1 ? '正常' : '禁用',
      error: '',
    };
    if (!row.tenantId) row.error = '企业租户ID必填';
    else if (!tenants.value.some((tenant) => tenant.id === row.tenantId)) row.error = '企业租户ID不存在';
    else if (!row.username) row.error = '用户名必填';
    else if (!row.email) row.error = '邮箱必填';
    else if (row.password && row.password.length < 8) row.error = '密码至少 8 位';
    return row;
  });
}

function parseMemberTable(text: string) {
  const lines = text
    .replace(/^\uFEFF/, '')
    .split(/\r?\n/)
    .map((line) => line.trim())
    .filter(Boolean);
  const delimiter = lines[0]?.includes('\t') ? '\t' : ',';
  return buildImportRows(lines.map((line) => splitDelimitedLine(line, delimiter)));
}

async function handleImportFile(file: any) {
  const raw = file.raw;
  if (!raw) return;
  const fileName = String(raw.name || '').toLowerCase();
  if (fileName.endsWith('.xlsx')) {
    const rows = await readXlsxFile(raw) as unknown as unknown[][];
    importRows.value = buildImportRows(rows.map((line) => line.map((cell) => String(cell || ''))));
  } else {
    const text = await raw.text();
    importRows.value = parseMemberTable(text);
  }
  importResults.value = [];
}

function openImportMembers() {
  importRows.value = [];
  importResults.value = [];
  importDialog.value = true;
}

async function submitImportMembers() {
  if (!importValidRows.value.length) {
    ElMessage.warning('没有可导入的有效员工');
    return;
  }
  importing.value = true;
  try {
    const groups = new Map<number, any[]>();
    importValidRows.value.forEach((row) => {
      const rows = groups.get(row.tenantId) || [];
      rows.push(row);
      groups.set(row.tenantId, rows);
    });
    const results: any[] = [];
    for (const [tenantId, rows] of groups.entries()) {
      const groupResults = await http.post(`/tenants/${tenantId}/members/import`, rows.map((row) => ({
        username: row.username,
        email: row.email,
        phone: row.phone,
        role: row.role,
        position: row.position,
        password: row.password,
        status: row.status,
      })));
      groupResults.forEach((result: any, index: number) => {
        results.push({
          ...result,
          tenantId,
          tenantName: rows[index]?.tenantName,
          rowNumber: rows[index]?.rowNumber,
        });
      });
    }
    importResults.value = results;
    const success = results.filter((row) => row.success).length;
    ElMessage.success(`导入完成：成功 ${success} 条，失败 ${results.length - success} 条`);
    if (success) await load();
  } finally {
    importing.value = false;
  }
}

async function setStatus(row: UserOrganizationRow, status: number) {
  await http.patch(`/users/${row.userId}/status`, { status });
  await load();
}

async function kickout(row: UserOrganizationRow) {
  await http.post(`/users/${row.userId}/kickout`);
  ElMessage.success('已强制下线该员工账号');
}

async function resetPassword(row: UserOrganizationRow) {
  const res = await http.post<any>(`/users/${row.userId}/reset-password`);
  ElMessage.success(`新密码：${res.password}`);
}

onMounted(() => {
  applyRouteQuery();
  loadTenants();
  load();
});
watch(() => route.query, () => {
  applyRouteQuery();
  load();
});
</script>

<template>
  <div>
    <div class="page-head">
      <div>
        <h1>组织员工</h1>
        <p>明确平台、企业租户与组织员工之间的数据归属、权限范围和操作边界</p>
      </div>
      <div class="page-actions">
        <el-button @click="downloadImportTemplate">下载模板</el-button>
        <el-button @click="openImportMembers">批量导入</el-button>
        <el-button type="primary" @click="openCreateMember">新增员工</el-button>
      </div>
    </div>

    <div class="hierarchy-grid">
      <section v-for="item in hierarchy" :key="item.title" class="hierarchy-card">
        <b>{{ item.title }}</b>
        <span>{{ item.subtitle }}</span>
        <ul>
          <li v-for="point in item.points" :key="point">{{ point }}</li>
        </ul>
      </section>
    </div>

    <div class="toolbar">
      <el-input v-model="query.keyword" clearable placeholder="搜索企业、租户标识、员工姓名、邮箱或手机" style="width: 360px" @keyup.enter="search" />
      <el-input v-model="query.tenantId" clearable placeholder="租户编号" style="width: 180px" @keyup.enter="search" />
      <el-select v-model="query.status" clearable placeholder="账号状态" style="width: 160px">
        <el-option label="正常" :value="1" />
        <el-option label="禁用" :value="0" />
      </el-select>
      <el-button type="primary" @click="search">查询</el-button>
      <el-button @click="() => { query.keyword = ''; query.tenantId = ''; query.status = undefined; search(); }">重置</el-button>
    </div>

    <div class="panel">
      <div class="panel-title">
        <div>
          <b>员工组织关系列表</b>
          <span>从真实租户、成员关系和配额表读取，展示每个账号的数据边界与组织权限</span>
        </div>
        <div class="panel-tools">
          <el-button @click="downloadImportTemplate">下载模板</el-button>
          <el-button @click="openImportMembers">批量导入</el-button>
          <el-button type="primary" @click="openCreateMember">新增员工</el-button>
        </div>
      </div>
      <div class="org-list">
        <article v-for="row in page.records" :key="row.userId" class="org-row">
          <section class="org-row-main">
            <div class="org-tenant-block">
              <label>企业租户</label>
              <strong>{{ row.tenantName }}</strong>
              <div class="org-tags">
                <el-tag size="small" effect="plain">{{ planLabel(row.tenantPlan) }}</el-tag>
                <el-tag size="small" :type="statusType(row.tenantStatus)" effect="plain">{{ statusLabel(row.tenantStatus) }}</el-tag>
              </div>
            </div>
            <div class="org-user-block">
              <label>员工账号</label>
              <strong>{{ row.username }}</strong>
              <span>{{ row.email }}</span>
            </div>
            <div class="org-member-block">
              <label>组织关系</label>
              <strong>{{ roleLabel(row.memberRole) }}</strong>
              <span>{{ row.position || '未设置岗位' }}</span>
              <el-tag size="small" :type="statusType(row.status)" effect="plain">{{ statusLabel(row.status) }}</el-tag>
            </div>
          </section>
          <section class="org-actions">
            <el-button type="primary" plain @click="detailRow = row">详情</el-button>
            <el-button type="primary" plain @click="setStatus(row, row.status === 1 ? 0 : 1)">
              {{ row.status === 1 ? '禁用' : '启用' }}
            </el-button>
            <el-button @click="kickout(row)">下线</el-button>
            <el-button @click="resetPassword(row)">重置</el-button>
          </section>
        </article>
        <el-empty v-if="page.records.length === 0" description="暂无员工组织关系数据" />
      </div>
      <div class="table-footer">
        <el-pagination
          v-model:current-page="query.page"
          v-model:page-size="query.size"
          layout="total, prev, pager, next, sizes"
          :page-sizes="pageSizes"
          :total="page.total"
          @current-change="load"
          @size-change="search"
        />
      </div>
    </div>

    <el-drawer v-model="detailVisible" title="员工组织关系详情" size="520px" class="org-detail-drawer">
      <div v-if="detailRow" class="org-detail">
        <section class="org-detail-hero">
          <span>员工账号</span>
          <strong>{{ detailRow.username }}</strong>
          <p>{{ detailRow.email }} · {{ detailRow.phone || '未填写手机号' }}</p>
          <div>
            <el-tag :type="statusType(detailRow.status)" effect="plain">{{ statusLabel(detailRow.status) }}</el-tag>
            <el-tag effect="plain">{{ roleLabel(detailRow.memberRole || detailRow.accountRole) }}</el-tag>
          </div>
        </section>

        <section class="org-detail-section">
          <b>企业归属</b>
          <div class="org-detail-grid">
            <label><span>企业租户</span><strong>{{ detailRow.tenantName }}</strong></label>
            <label><span>租户标识</span><strong>{{ detailRow.tenantSlug }}</strong></label>
            <label><span>租户编号</span><strong>{{ detailRow.tenantId }}</strong></label>
            <label><span>套餐</span><strong>{{ planLabel(detailRow.tenantPlan) }}</strong></label>
            <label><span>租户状态</span><strong>{{ statusLabel(detailRow.tenantStatus) }}</strong></label>
          </div>
        </section>

        <section class="org-detail-section">
          <b>组织关系</b>
          <div class="org-detail-grid">
            <label><span>成员关系编号</span><strong>{{ detailRow.memberId || '-' }}</strong></label>
            <label><span>组织角色</span><strong>{{ roleLabel(detailRow.memberRole || detailRow.accountRole) }}</strong></label>
            <label><span>岗位</span><strong>{{ detailRow.position || '未设置岗位' }}</strong></label>
            <label><span>加入时间</span><strong>{{ formatTime(detailRow.joinedAt) }}</strong></label>
            <label><span>最近登录</span><strong>{{ formatTime(detailRow.lastLoginAt) }}</strong></label>
          </div>
        </section>

        <section class="org-detail-section">
          <b>权限与数据边界</b>
          <p>{{ detailRow.permissionScope || '未配置权限说明' }}</p>
          <p>{{ detailRow.dataBoundary || '未配置数据边界说明' }}</p>
          <div class="quota-strip">
            <span>成员上限 {{ detailRow.maxMembers ?? '-' }}</span>
            <span>项目上限 {{ detailRow.maxProjects ?? '-' }}</span>
            <span>并发任务 {{ detailRow.maxConcurrentTasks ?? '-' }}</span>
          </div>
        </section>

        <section class="org-detail-actions">
          <el-button type="primary" plain @click="setStatus(detailRow, detailRow.status === 1 ? 0 : 1)">
            {{ detailRow.status === 1 ? '禁用账号' : '启用账号' }}
          </el-button>
          <el-button @click="kickout(detailRow)">强制下线</el-button>
          <el-button @click="resetPassword(detailRow)">重置密码</el-button>
        </section>
      </div>
    </el-drawer>

    <el-dialog v-model="memberDialog" title="新增组织员工" width="640px" class="admin-form-dialog">
      <el-form label-position="top">
        <el-form-item label="所属企业">
          <el-select v-model="memberForm.tenantId" filterable placeholder="请选择企业租户">
            <el-option
              v-for="tenant in tenants"
              :key="tenant.id"
              :label="tenantLabel(tenant)"
              :value="tenant.id"
            />
          </el-select>
        </el-form-item>
        <div class="form-grid-2">
          <el-form-item label="员工账号">
            <el-input v-model="memberForm.username" placeholder="例如 ops_editor" />
          </el-form-item>
          <el-form-item label="邮箱">
            <el-input v-model="memberForm.email" placeholder="用于登录和通知" />
          </el-form-item>
          <el-form-item label="手机号">
            <el-input v-model="memberForm.phone" placeholder="可选" />
          </el-form-item>
          <el-form-item label="初始密码">
            <el-input v-model="memberForm.password" type="password" show-password placeholder="为空则使用默认密码" />
          </el-form-item>
          <el-form-item label="组织角色">
            <el-select v-model="memberForm.role">
              <el-option label="所有者" value="owner" />
              <el-option label="管理员" value="admin" />
              <el-option label="成员" value="member" />
            </el-select>
          </el-form-item>
          <el-form-item label="岗位">
            <el-input v-model="memberForm.position" placeholder="例如 项目协作成员" />
          </el-form-item>
          <el-form-item label="账号状态">
            <el-radio-group v-model="memberForm.status">
              <el-radio-button :value="1">正常</el-radio-button>
              <el-radio-button :value="0">禁用</el-radio-button>
            </el-radio-group>
          </el-form-item>
        </div>
      </el-form>
      <template #footer>
        <el-button @click="memberDialog = false">取消</el-button>
        <el-button type="primary" @click="saveMember">写入数据库</el-button>
      </template>
    </el-dialog>

    <el-dialog v-model="importDialog" title="批量导入组织员工" width="980px" class="member-import-dialog">
      <div class="member-import-layout">
        <section class="import-uploader">
          <el-upload
            drag
            accept=".xlsx,.csv,.txt"
            :auto-upload="false"
            :show-file-list="false"
            :on-change="handleImportFile"
          >
            <div class="upload-text">
              <b>上传员工表格</b>
              <span>模板内必须填写企业租户ID，支持 Excel xlsx、CSV 文件。</span>
            </div>
          </el-upload>
          <el-button @click="downloadImportTemplate">下载导入模板</el-button>
        </section>
        <section class="import-summary">
          <strong>{{ importValidRows.length }}</strong>
          <small>有效行 / 共 {{ importRows.length }} 行</small>
          <div v-if="importResults.length">
            <el-tag type="success" effect="plain">成功 {{ importSuccessCount }}</el-tag>
            <el-tag type="danger" effect="plain">失败 {{ importFailCount }}</el-tag>
          </div>
        </section>
      </div>

      <div class="import-preview-table">
        <el-table :data="importResults.length ? importResults : importRows" max-height="360">
          <el-table-column prop="rowNumber" label="行号" width="80" />
          <el-table-column label="企业租户" min-width="180">
            <template #default="{ row }">
              <div class="relation-cell">
                <strong>{{ row.tenantName || row.tenantId || '-' }}</strong>
                <small v-if="row.tenantId">ID {{ row.tenantId }}</small>
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="username" label="员工账号" min-width="160" />
          <el-table-column prop="email" label="邮箱" min-width="220" />
          <el-table-column prop="phone" label="手机号" width="140" />
          <el-table-column prop="roleLabel" label="组织角色" width="110" />
          <el-table-column prop="position" label="岗位" min-width="140" />
          <el-table-column label="校验/结果" min-width="180">
            <template #default="{ row }">
              <el-tag v-if="importResults.length" :type="row.success ? 'success' : 'danger'" effect="plain">
                {{ row.message }}
              </el-tag>
              <el-tag v-else-if="row.error" type="danger" effect="plain">{{ row.error }}</el-tag>
              <el-tag v-else type="success" effect="plain">可导入</el-tag>
            </template>
          </el-table-column>
        </el-table>
        <el-empty v-if="!importRows.length && !importResults.length" description="请先上传员工表格" />
      </div>

      <template #footer>
        <el-button @click="importDialog = false">取消</el-button>
        <el-button type="primary" :loading="importing" :disabled="!importValidRows.length" @click="submitImportMembers">
          导入到数据库
        </el-button>
      </template>
    </el-dialog>
  </div>
</template>
