<script lang="ts" setup>
import { computed, onMounted, watch } from 'vue';

import { Page, useVbenModal } from '@vben/common-ui';

import { Button, Empty, Tabs, message } from 'ant-design-vue';
import { PlusOutlined } from '@ant-design/icons-vue';

import { useVbenVxeGrid } from '#/adapter/vxe-table';
import type { ContextMenuItem } from '#/components/context-menu';
import { showContextMenu } from '#/components/context-menu';

import { deleteProcess, updateProcess } from './api';
import InlineFieldEditor from './components/inline-field-editor.vue';
import MethodInfoBar from './components/method-info-bar.vue';
import FormModalDemo from './components/modal.vue';
import MovePidModal from './components/move-pid-modal.vue';
import ConfigSectionHeader from '#/views/system/shared/config-section-header.vue';
import ConfigTreeSidebar from '#/views/system/shared/config-tree-sidebar.vue';
import type { TreeSidebarRow } from '#/views/system/shared/types';
import { useProcessTree } from './composables/useProcessTree';
import type { ProcessNoteRow, ProcessRuleRow } from './constants';
import { noteGridOptions } from './config/note-table';

const {
  allLevel2Rules,
  currentMethods,
  currentNotes,
  filteredLevel1,
  keyword,
  level1List,
  loadData,
  loading,
  patchNote,
  patchRule,
  selectLevel1,
  selectMethod,
  selectedLevel1,
  selectedLevel1Id,
  selectedMethod,
  selectedMethodId,
} = useProcessTree();

const breadcrumbMethodName = computed(
  () => selectedMethod.value?.name ?? '未选择煎法',
);

const [FormModal, formModalApi] = useVbenModal({
  connectedComponent: FormModalDemo,
});

const [MoveModal, moveModalApi] = useVbenModal({
  connectedComponent: MovePidModal,
});

const [NoteGrid, noteGridApi] = useVbenVxeGrid({
  gridOptions: {
    ...noteGridOptions,
    data: [],
  },
});

function syncNoteGrid() {
  noteGridApi.setGridOptions({ data: currentNotes.value });
}

onMounted(async () => {
  await loadData();
  syncNoteGrid();
});

watch(currentNotes, syncNoteGrid, { deep: true });
watch(selectedMethodId, syncNoteGrid);

function refresh() {
  return loadData().then(syncNoteGrid);
}

function openCreateModal(options: {
  formLevel: number;
  isUpdate?: boolean;
  parentRow?: Record<string, any>;
  values?: Record<string, any>;
}) {
  const { formLevel, isUpdate = false, parentRow, values = {} } = options;
  let formValues: Record<string, any> = { ...values, formLevel };

  if (!isUpdate) {
    if (formLevel === 1) {
      formValues = { node_type: 'rule', pid: 0, formLevel: 1 };
    } else if (formLevel === 2 && parentRow) {
      formValues = {
        node_type: 'rule',
        pid: parentRow.id,
        formLevel: 2,
      };
    } else if (formLevel === 3 && parentRow) {
      formValues = {
        node_type: 'note',
        rule_id: parentRow.id,
        formLevel: 3,
        volume: 50,
      };
    }
  } else if (formLevel === 3) {
    formValues = {
      ...values,
      formLevel: 3,
      note: values.note ?? values.name,
      rule_id: values.rule_id ?? values.pid,
      real_id: values.real_id ?? Math.abs(Number(values.id)),
    };
  } else {
    formValues = {
      ...values,
      formLevel,
      has_children: values.has_children ?? false,
    };
  }

  formModalApi.setData({
    values: formValues,
    update: isUpdate,
    formLevel,
    onSuccess: refresh,
  });
  formModalApi.open();
}

function openMoveModal(
  target:
    | { kind: 'method'; row: ProcessRuleRow }
    | { kind: 'note'; row: ProcessNoteRow },
) {
  moveModalApi.setData({
    target,
    level1List: level1List.value,
    allMethods: allLevel2Rules(),
    onSuccess: refresh,
  });
  moveModalApi.open();
}

function buildLevel1Menus(row: ProcessRuleRow): ContextMenuItem[] {
  return [
    {
      key: 'add-method',
      label: '新增煎法',
      handler: () => openCreateModal({ formLevel: 2, parentRow: row }),
    },
  ];
}

function buildMethodMenus(row: ProcessRuleRow): ContextMenuItem[] {
  return [
    {
      key: 'add-note',
      label: '新增备注',
      handler: () => openCreateModal({ formLevel: 3, parentRow: row }),
    },
    {
      key: 'move-pid',
      label: '移动父级',
      handler: () => openMoveModal({ kind: 'method', row }),
    },
  ];
}

function buildNoteMenus(row: ProcessNoteRow): ContextMenuItem[] {
  const method = selectedMethod.value;
  return [
    {
      key: 'add-note',
      label: '新增备注',
      handler: () => {
        if (method) {
          openCreateModal({ formLevel: 3, parentRow: method });
        }
      },
    },
    {
      key: 'move-pid',
      label: '移动父级',
      handler: () => openMoveModal({ kind: 'note', row }),
    },
    {
      key: 'delete',
      label: '删除',
      handler: async () => {
        await deleteProcess({ ids: [row.id] });
        message.success('删除成功');
        await refresh();
      },
    },
  ];
}

function onLevel1ContextMenu(e: MouseEvent, row: TreeSidebarRow) {
  showContextMenu(e, buildLevel1Menus(row as ProcessRuleRow), row);
}

function onMethodTabContextMenu(e: MouseEvent, row: ProcessRuleRow) {
  showContextMenu(e, buildMethodMenus(row), row);
}

function onNoteContextMenu(e: MouseEvent, row: ProcessNoteRow) {
  showContextMenu(e, buildNoteMenus(row), row);
}

async function saveLevel1Name(row: TreeSidebarRow, name: string) {
  const rule = row as ProcessRuleRow;
  await updateProcess({ id: rule.id, node_type: 'rule', name });
  patchRule(rule.id, { name });
  message.success('保存成功');
}

async function saveNoteField(
  row: ProcessNoteRow,
  field: 'name' | 'volume',
  value: number | string,
) {
  const payload: Record<string, unknown> = {
    id: row.id,
    node_type: 'note',
    real_id: row.real_id,
    note: row.note ?? row.name,
  };
  if (field === 'name') {
    payload.note = value;
  } else {
    payload.volume = value;
  }
  await updateProcess(payload);
  patchNote(row.id, field === 'name' ? { name: String(value) } : { volume: Number(value) });
  message.success('保存成功');
}

function onTabChange(key: string | number) {
  selectMethod(Number(key));
  syncNoteGrid();
}

function onSelectLevel1(id: number) {
  selectLevel1(id);
  syncNoteGrid();
}

function openCreateMethod() {
  if (!selectedLevel1.value) {
    return;
  }
  openCreateModal({ formLevel: 2, parentRow: selectedLevel1.value });
}

function openCreateNote() {
  if (!selectedMethod.value) {
    return;
  }
  openCreateModal({ formLevel: 3, parentRow: selectedMethod.value });
}
</script>

<template>
  <Page
    auto-content-height
    description="右键制剂、煎法 Tab 或备注行可新增/移动；点击虚线下划线字段可编辑"
    title="加工费管理"
  >
    <FormModal />
    <MoveModal />

    <div class="flex h-full min-h-0 gap-4">
      <ConfigTreeSidebar
        add-label="新增制剂"
        empty-text="暂无制剂"
        :filtered-level1="filteredLevel1"
        :keyword="keyword"
        :loading="loading"
        search-placeholder="搜索制剂名称"
        :selected-level1-id="selectedLevel1Id"
        title="制剂"
        :total-count="level1List.length"
        @add-level1="openCreateModal({ formLevel: 1 })"
        @contextmenu="onLevel1ContextMenu"
        @save-name="saveLevel1Name"
        @select="onSelectLevel1"
        @update:keyword="(val) => (keyword = val)"
      />

      <main
        class="min-w-0 flex-1 rounded-lg border border-border bg-card px-4 py-3 dark:border-gray-700"
      >
        <template v-if="selectedLevel1">
          <div class="space-y-4">
            <div
              class="flex flex-wrap items-center justify-between gap-3 border-b border-border pb-3"
            >
              <div class="flex min-w-0 flex-wrap items-center gap-2 text-sm">
                <span class="font-medium text-foreground">{{
                  selectedLevel1.name
                }}</span>
                <span class="text-muted-foreground">/</span>
                <span
                  :class="
                    selectedMethod
                      ? 'text-foreground'
                      : 'text-muted-foreground'
                  "
                >
                  {{ breadcrumbMethodName }}
                </span>
              </div>
              <div class="flex shrink-0 flex-wrap items-center gap-2">
                <Button size="small" @click="openCreateMethod">
                  <PlusOutlined />
                  新增煎法
                </Button>
                <Button
                  size="small"
                  type="primary"
                  :disabled="!selectedMethod"
                  @click="openCreateNote"
                >
                  <PlusOutlined />
                  新增备注
                </Button>
              </div>
            </div>

            <section>
              <Tabs
                v-if="currentMethods.length"
                :active-key="String(selectedMethodId ?? '')"
                class="process-method-tabs select-none"
                type="line"
                @change="onTabChange"
              >
                <Tabs.TabPane
                  v-for="method in currentMethods"
                  :key="String(method.id)"
                >
                  <template #tab>
                    <span
                      class="cursor-pointer"
                      @contextmenu.prevent="
                        onMethodTabContextMenu($event, method)
                      "
                    >
                      {{ method.name }}
                    </span>
                  </template>
                </Tabs.TabPane>
              </Tabs>
              <div
                v-else
                class="flex flex-col items-center justify-center rounded-lg border border-dashed border-border py-8 dark:border-gray-700"
              >
                <Empty description="暂无煎法" />
                <Button class="mt-4" type="primary" @click="openCreateMethod">
                  <PlusOutlined />
                  新增煎法
                </Button>
              </div>
            </section>

            <MethodInfoBar
              :method="selectedMethod"
              @updated="
                (patch) => selectedMethod && patchRule(selectedMethod.id, patch)
              "
            />

            <section
              class="rounded-lg border border-border dark:border-gray-700"
            >
              <ConfigSectionHeader
                class="mb-3 px-4 pt-3"
                :subtitle="selectedMethod ? `共 ${currentNotes.length} 条` : undefined"
                title="备注列表"
              >
                <template #actions>
                  <Button
                    size="small"
                    type="primary"
                    :disabled="!selectedMethod"
                    @click="openCreateNote"
                  >
                    <PlusOutlined />
                    新增备注
                  </Button>
                </template>
              </ConfigSectionHeader>

              <div
                v-if="selectedMethod && currentNotes.length"
                class="overflow-hidden rounded-b-lg border-t border-border dark:border-gray-700"
              >
                <NoteGrid @contextmenu.prevent>
                  <template #name="{ row }">
                    <span @contextmenu="onNoteContextMenu($event, row)">
                      <InlineFieldEditor
                        :value="row.name"
                        @save="(val) => saveNoteField(row, 'name', val)"
                      />
                    </span>
                  </template>
                  <template #volume="{ row }">
                    <span @contextmenu="onNoteContextMenu($event, row)">
                      <InlineFieldEditor
                        type="number"
                        :value="row.volume"
                        :display-formatter="
                          (val) =>
                            val !== null && val !== undefined && val !== ''
                              ? `${val}ml`
                              : '点击设置'
                        "
                        @save="(val) => saveNoteField(row, 'volume', val)"
                      />
                    </span>
                  </template>
                </NoteGrid>
              </div>
              <div
                v-else-if="selectedMethod"
                class="flex flex-col items-center justify-center px-4 py-8"
              >
                <Empty description="暂无备注" />
                <Button class="mt-4" type="primary" @click="openCreateNote">
                  <PlusOutlined />
                  新增备注
                </Button>
              </div>
              <div v-else class="px-4 pb-4">
                <Empty description="请先选择煎法" />
              </div>
            </section>
          </div>
        </template>
        <Empty v-else description="请选择左侧制剂" />
      </main>
    </div>
  </Page>
</template>

<style scoped>
.process-method-tabs :deep(.ant-tabs-nav) {
  margin-bottom: 0;
}

.process-method-tabs :deep(.ant-tabs-tab) {
  transition: color 0.2s;
}
</style>
