<script setup lang="ts">
import { ref, computed, watch, onMounted } from 'vue';
import TreeTable from 'primevue/treetable';
import Column from 'primevue/column';
import Select from 'primevue/select';
import Button from 'primevue/button';
import Tag from 'primevue/tag';
import { useToast } from 'primevue/usetoast';
import BasePageHeader from '@/core/components/BasePageHeader.vue';
import WbsUploadDialog from '../components/WbsUploadDialog.vue';
import WbsVersionSelect from '../components/WbsVersionSelect.vue';
import { useWbsStore } from '../wbs.store';
import { projectService } from '@/modules/project/project.service';
import type { Project } from '@/modules/project/project.types';
import type { WbsVersion, WbsNode } from '../wbs.types';

const toast = useToast();
const wbsStore = useWbsStore();

const projects = ref<Project[]>([]);
const selectedProject = ref<Project | null>(null);
const selectedVersion = ref<WbsVersion | null>(null);
const uploadDialogVisible = ref(false);
const uploadLoading = ref(false);

// Build tree nodes for PrimeVue TreeTable
interface TreeNode {
  key: string;
  data: WbsNode;
  children: TreeNode[];
}

const treeNodes = computed<TreeNode[]>(() => {
  const nodes = wbsStore.nodes;
  if (!nodes || nodes.length === 0) return [];

  const nodeMap = new Map<string, TreeNode>();
  const roots: TreeNode[] = [];

  // Create tree node objects
  for (const node of nodes) {
    nodeMap.set(node.wbsCode, {
      key: node.wbsCode,
      data: node,
      children: [],
    });
  }

  // Build hierarchy
  for (const node of nodes) {
    const treeNode = nodeMap.get(node.wbsCode)!;
    const parentCode = deriveParentCode(node.wbsCode, node.level);
    if (parentCode && nodeMap.has(parentCode)) {
      nodeMap.get(parentCode)!.children.push(treeNode);
    } else {
      roots.push(treeNode);
    }
  }

  return roots;
});

function deriveParentCode(wbsCode: string, level: number): string | null {
  if (level <= 1) return null;
  const lastDot = wbsCode.lastIndexOf('.');
  return lastDot > 0 ? wbsCode.substring(0, lastDot) : null;
}

const canActivate = computed(() => {
  return selectedVersion.value?.status === 'DRAFT';
});

async function loadProjects() {
  try {
    const { data } = await projectService.getAll();
    projects.value = (data as any).items ?? data;
  } catch {
    toast.add({ severity: 'error', summary: '오류', detail: '프로젝트 목록 로드 실패', life: 5000 });
  }
}

async function loadVersions() {
  if (!selectedProject.value) return;
  try {
    await wbsStore.fetchVersions(selectedProject.value.id);
    selectedVersion.value = null;
  } catch {
    toast.add({ severity: 'error', summary: '오류', detail: 'WBS 버전 목록 로드 실패', life: 5000 });
  }
}

async function loadNodes() {
  if (!selectedProject.value || !selectedVersion.value) return;
  try {
    await wbsStore.fetchNodes(selectedProject.value.id, selectedVersion.value.versionNumber);
  } catch {
    toast.add({ severity: 'error', summary: '오류', detail: 'WBS 노드 로드 실패', life: 5000 });
  }
}

async function onActivate() {
  if (!selectedProject.value || !selectedVersion.value) return;
  try {
    await wbsStore.activateVersion(selectedProject.value.id, selectedVersion.value.versionNumber);
    toast.add({ severity: 'success', summary: '성공', detail: 'WBS 버전이 활성화되었습니다.', life: 3000 });
    selectedVersion.value = null;
  } catch {
    toast.add({ severity: 'error', summary: '오류', detail: '버전 활성화 실패', life: 5000 });
  }
}

async function onUpload(payload: { file: File; effectiveDate: string; description: string }) {
  if (!selectedProject.value) return;
  uploadLoading.value = true;
  try {
    await wbsStore.uploadWbs(selectedProject.value.id, payload.file, payload.effectiveDate);
    toast.add({ severity: 'success', summary: '성공', detail: 'P6 WBS 파일이 업로드되었습니다.', life: 3000 });
    uploadDialogVisible.value = false;
  } catch {
    toast.add({ severity: 'error', summary: '오류', detail: 'WBS 업로드 실패', life: 5000 });
  } finally {
    uploadLoading.value = false;
  }
}

function statusSeverity(status: string): string {
  const map: Record<string, string> = {
    DRAFT: 'warn',
    ACTIVE: 'success',
    ARCHIVED: 'secondary',
  };
  return map[status] ?? 'secondary';
}

function statusLabel(status: string): string {
  const map: Record<string, string> = {
    DRAFT: '초안',
    ACTIVE: '활성',
    ARCHIVED: '보관',
  };
  return map[status] ?? status;
}

watch(selectedProject, () => {
  loadVersions();
  wbsStore.nodes = [];
});

watch(selectedVersion, () => {
  if (selectedVersion.value) {
    loadNodes();
  } else {
    wbsStore.nodes = [];
  }
});

onMounted(loadProjects);
</script>

<template>
  <div class="wbs-tree-view">
    <BasePageHeader title="WBS 관리">
      <template #actions>
        <Button
          label="P6 업로드"
          icon="pi pi-upload"
          :disabled="!selectedProject"
          @click="uploadDialogVisible = true"
        />
      </template>
    </BasePageHeader>

    <!-- Top bar: selectors -->
    <div class="wbs-tree-view__toolbar">
      <div class="wbs-tree-view__selector">
        <label class="wbs-tree-view__label">프로젝트</label>
        <Select
          v-model="selectedProject"
          :options="projects"
          optionLabel="name"
          placeholder="프로젝트 선택"
          fluid
          style="min-width: 240px"
        />
      </div>
      <div class="wbs-tree-view__selector">
        <label class="wbs-tree-view__label">버전</label>
        <WbsVersionSelect
          v-model="selectedVersion"
          :versions="wbsStore.versions"
          :loading="wbsStore.loading"
          style="min-width: 200px"
        />
      </div>
      <Button
        v-if="canActivate"
        label="활성화"
        icon="pi pi-check"
        severity="success"
        @click="onActivate"
      />
    </div>

    <!-- TreeTable -->
    <div class="wbs-tree-view__content">
      <TreeTable
        :value="treeNodes"
        :loading="wbsStore.loading"
        removableSort
        stripedRows
        showGridlines
        responsiveLayout="scroll"
        size="small"
      >
        <template #empty>
          <div class="wbs-tree-view__empty">
            <i class="pi pi-inbox" style="font-size: 2rem" />
            <p>프로젝트와 버전을 선택해 주세요.</p>
          </div>
        </template>
        <Column field="wbsCode" header="WBS Code" sortable style="min-width: 200px" expander />
        <Column field="name" header="이름" sortable style="min-width: 200px" />
        <Column field="level" header="Level" sortable style="min-width: 80px" />
        <Column field="discipline" header="Discipline" sortable style="min-width: 120px" />
        <Column field="plannedHours" header="계획시수" sortable style="min-width: 100px">
          <template #body="{ node }">
            {{ node.data.plannedHours != null ? node.data.plannedHours.toLocaleString() : '-' }}
          </template>
        </Column>
        <Column header="상태" style="min-width: 80px">
          <template #body>
            <Tag
              v-if="selectedVersion"
              :value="statusLabel(selectedVersion.status)"
              :severity="statusSeverity(selectedVersion.status)"
            />
          </template>
        </Column>
      </TreeTable>
    </div>

    <WbsUploadDialog
      :visible="uploadDialogVisible"
      :loading="uploadLoading"
      @update:visible="uploadDialogVisible = $event"
      @upload="onUpload"
    />
  </div>
</template>

<style lang="scss" scoped>
@use '@/assets/styles/variables' as *;

.wbs-tree-view {
  &__toolbar {
    display: flex;
    align-items: flex-end;
    gap: $space-md;
    flex-wrap: wrap;
    margin-bottom: $space-lg;
  }

  &__selector {
    display: flex;
    flex-direction: column;
    gap: $space-xs;
  }

  &__label {
    font-size: $font-size-sm;
    font-weight: 600;
    color: $color-text-muted;
  }

  &__content {
    background: var(--surface-card);
    border-radius: $radius-md;
    overflow: hidden;
  }

  &__empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: $space-sm;
    padding: $space-2xl;
    color: $color-text-muted;
  }

  @media (max-width: $bp-mobile) {
    &__toolbar {
      flex-direction: column;
      align-items: stretch;
    }
  }
}
</style>
