import assert from 'node:assert/strict';
import test from 'node:test';
import type { Template } from '@pdfme/common';
import type { ResolvedDocumentTemplate } from '@/features/foundation/document-template/types';
import type { QuotationDocumentData } from '../types';
import { buildQuotationPdfRuntime } from './quotation-pdf-runtime';
import { resolveTemplatePages } from './page-resolver';
import type { ResolvedTemplate } from './runtime-contracts';
import { adaptTemplateForSectionRuntime } from './template-compatibility-adapter';

function createField(name: string, y: number, height = 7, type = 'text', content?: string) {
  return {
    name,
    type,
    position: { x: 10, y },
    width: 100,
    height,
    content: content ?? `{${name}}`,
  };
}

function createMarker(role: string) {
  return {
    name: `__section_role__${role}`,
    type: 'text',
    position: { x: 1, y: 1 },
    width: 8,
    height: 2,
    content: role,
    readOnly: true,
    opacity: 0,
  };
}

function createLegacyTemplate(): Template {
  return {
    basePdf: { width: 210, height: 297, padding: [0, 0, 0, 0] },
    schemas: [
      [
        createField('customer_name', 20),
        createField('quotation_price_data', 40, 20, 'table', '[["Price (Exclude VAT)","-","","THB"]]'),
        createField('quotation_code_data', 70),
      ],
      [
        createField('topic', 35, 10, 'table', '[["Topic:"]]'),
        createField('data_topic', 45, 10, 'table', '[["{item_topic}"]]'),
        createField('Please_do_not', 225),
        createField('yours_faithfuly', 232),
        createField('app1', 240),
        createField('app1_position', 247),
        createField('app2', 240),
        createField('app2_position', 247),
        createField('app3', 240),
        createField('app3_position', 247),
      ],
    ],
  } as unknown as Template;
}

function createProductTemplate(): Template {
  return {
    basePdf: { width: 210, height: 297, padding: [0, 0, 0, 0] },
    schemas: [
      [
        createMarker('customer'),
        createField('customer_name', 20),
        createField('quotation_code_data', 30),
      ],
      [
        createMarker('product_items'),
        {
          name: 'items_table',
          type: 'table',
          position: { x: 10, y: 40 },
          width: 180,
          height: 120,
          content: '[["1","Sample","1","EA","THB 1.00","THB 0.00","THB 1.00"]]',
          showHead: true,
          repeatHead: true,
          head: ['Item', 'Description', 'Qty', 'Unit', 'Unit Price', 'Discount', 'Total'],
          headWidthPercentages: [8, 34, 8, 10, 14, 12, 14],
        },
      ],
      [
        createMarker('topics'),
        createMarker('signature'),
        createField('topic', 35, 10, 'table', '[["Topic:"]]'),
        createField('data_topic', 45, 10, 'table', '[["{item_topic}"]]'),
        createField('Please_do_not', 225),
        createField('yours_faithfuly', 232),
        createField('app1', 240),
        createField('app1_position', 247),
        createField('app2', 240),
        createField('app2_position', 247),
        createField('app3', 240),
        createField('app3_position', 247),
      ],
    ],
  } as unknown as Template;
}

function createResolvedDocumentTemplate(schema: Template): ResolvedDocumentTemplate {
  return {
    template: {
      id: 'template-1',
      organizationId: 'org-1',
      documentType: 'quotation',
      productType: 'default',
      fileType: 'pdfme',
      templateName: 'Quotation template',
      description: null,
      isDefault: true,
      isActive: true,
      createdAt: '2026-06-29T00:00:00.000Z',
      updatedAt: '2026-06-29T00:00:00.000Z',
      deletedAt: null,
      createdBy: 'system',
      updatedBy: 'system',
    },
    version: {
      id: 'template-version-1',
      organizationId: 'org-1',
      templateId: 'template-1',
      version: '1.0',
      filePath: null,
      schemaJson: schema,
      previewImageUrl: null,
      isActive: true,
      createdAt: '2026-06-29T00:00:00.000Z',
      updatedAt: '2026-06-29T00:00:00.000Z',
      deletedAt: null,
      createdBy: 'system',
    },
  };
}

function createItem(index: number): QuotationDocumentData['items'][number] {
  return {
    id: `item-${index}`,
    itemNumber: index + 1,
    productTypeCode: null,
    productTypeLabel: null,
    description: `Product item ${index + 1}`,
    quantity: 1,
    unitCode: 'EA',
    unitLabel: 'EA',
    unitPrice: 1200 + index,
    discount: index * 10,
    discountTypeCode: null,
    taxRate: 0,
    totalPrice: 1200 + index - index * 10,
    notes: null,
  };
}

function createDocumentData(topicCount: number, itemCount = 0): QuotationDocumentData {
  return {
    company: {
      id: 'company-1',
      name: 'ALLA',
      slug: 'alla',
      imageUrl: null,
      plan: 'pro',
    },
    branch: null,
    customer: {
      id: 'customer-1',
      code: 'C-001',
      name: 'Customer',
      address: null,
      phone: null,
      email: null,
      taxId: null,
    },
    contact: null,
    quotation: {
      id: 'quotation-1',
      code: 'QT-TEST',
      quotationDate: '2026-06-29',
      validUntil: null,
      projectName: null,
      projectLocation: null,
      attention: null,
      reference: null,
      revision: 0,
      revisionLabel: 'Rev.0',
      statusCode: 'approved',
      statusLabel: 'Approved',
      quotationTypeCode: null,
      quotationTypeLabel: null,
      currency: 'THB',
      currencyCode: 'THB',
      currencyLabel: 'Thai Baht',
      exchangeRate: 1,
      subtotal: 0,
      discount: 0,
      discountTypeCode: null,
      discountTypeLabel: null,
      taxRate: 0,
      taxAmount: 0,
      totalAmount: 0,
      notes: null,
    },
    items: Array.from({ length: itemCount }, (_, index) => createItem(index)),
    quotationCustomers: [],
    topics: {
      scope: [],
      exclusion: [],
      payment: [],
      warranty: [],
      delivery: [],
      other: [],
      all: Array.from({ length: topicCount }, (_, index) => ({
        id: `topic-${index}`,
        topicType: `Topic ${index + 1}`,
        sortOrder: index,
        items: Array.from({ length: 6 }, (_, itemIndex) => ({
          id: `${index}-${itemIndex}`,
          content: `Topic ${index + 1} item ${itemIndex + 1}`,
          sortOrder: itemIndex,
        })),
      })),
    },
    pdfme: {
      labels: {
        tel: 'Tel',
        email: 'Email',
        att: 'Att',
        project: 'Project',
        location: 'Location',
      },
      quotation_date: '2026-06-29',
      quotation_price: 'THB 0.00',
      quotation_price_data: [],
      exclusion_data: [],
      topic_inputs: {},
    },
    approval: {
      requestId: null,
      workflowName: null,
      status: 'approved',
      approvedAt: '2026-06-29T00:00:00.000Z',
      currentStep: null,
      currentStepRoleName: null,
      approvers: [],
    },
    signatures: {
      preparedBy: { name: 'Prepared', position: 'Sales' },
      approvedBy: { name: 'Approved', position: 'Manager' },
      authorizedBy: { name: 'Authorized', position: 'Director' },
    },
    watermarkStatus: null,
  };
}

test('legacy template page roles are still inferred without page-index assumptions', () => {
  const schema = createLegacyTemplate();
  const template = createResolvedDocumentTemplate(schema);
  const runtimeTemplate: ResolvedTemplate = {
    documentTemplate: template,
    schema,
  };

  const compatible = adaptTemplateForSectionRuntime(runtimeTemplate);
  const resolved = resolveTemplatePages(compatible);

  assert.equal(resolved.byRole.customer?.[0]?.pageIndex, 0);
  assert.equal(resolved.byRole.topics?.[0]?.pageIndex, 1);
  assert.equal(resolved.byRole.signature?.[0]?.pageIndex, 1);
  assert.ok(compatible.issues.some((issue) => issue.code === 'LEGACY_COMPAT_MODE'));
});

test('runtime keeps signature block on last generated topic page for legacy templates', async () => {
  const schema = createLegacyTemplate();
  const template = createResolvedDocumentTemplate(schema);
  const runtime = await buildQuotationPdfRuntime({
    documentData: createDocumentData(12),
    template,
    mappings: [],
    templateInput: {
      customer_name: 'Customer',
    },
  });

  assert.ok(runtime.assembled.template.schemas.length > 2);
  assert.ok(Object.keys(runtime.topicInputs).some((key) => key.startsWith('topic_1_')));

  const topicPages = runtime.assembled.template.schemas.slice(1);
  const lastPageNames = new Set(
    topicPages.at(-1)?.map((field) => String((field as { name?: string }).name ?? '')) ?? [],
  );

  assert.ok(lastPageNames.has('app1'));

  for (const page of topicPages.slice(0, -1)) {
    const fieldNames = new Set(
      page.map((field) => String((field as { name?: string }).name ?? '')),
    );
    assert.equal(fieldNames.has('app1'), false);
  }
});

test('runtime restores legacy static labels into final template input', async () => {
  const schema = createLegacyTemplate();
  const template = createResolvedDocumentTemplate(schema);
  const runtime = await buildQuotationPdfRuntime({
    documentData: createDocumentData(1),
    template,
    mappings: [],
    templateInput: {
      customer_name: 'Customer',
    },
  });

  assert.equal(runtime.assembled.templateInput.tel_label, 'Tel');
  assert.equal(runtime.assembled.templateInput.email_label, 'Email');
  assert.equal(runtime.assembled.templateInput.att_label, 'Att');
  assert.equal(runtime.assembled.templateInput.project_label, 'Project');
  assert.equal(runtime.assembled.templateInput.site_label, 'Location');
});

test('explicit section markers resolve product item page and runtime injects items_table', async () => {
  const schema = createProductTemplate();
  const template = createResolvedDocumentTemplate(schema);
  const runtimeTemplate: ResolvedTemplate = {
    documentTemplate: template,
    schema,
  };

  const compatible = adaptTemplateForSectionRuntime(runtimeTemplate);
  const resolved = resolveTemplatePages(compatible);

  assert.equal(resolved.byRole.customer?.[0]?.pageIndex, 0);
  assert.equal(resolved.byRole.product_items?.[0]?.pageIndex, 1);
  assert.equal(resolved.byRole.topics?.[0]?.pageIndex, 2);
  assert.equal(resolved.byRole.signature?.[0]?.pageIndex, 2);
  assert.equal(compatible.issues.some((issue) => issue.code === 'LEGACY_COMPAT_MODE'), false);

  const runtime = await buildQuotationPdfRuntime({
    documentData: createDocumentData(4, 4),
    template,
    mappings: [],
    templateInput: {
      customer_name: 'Customer',
    },
  });

  assert.ok(runtime.assembled.template.schemas.length >= 3);
  const productPageNames = new Set(
    runtime.assembled.template.schemas[1]?.map((field) =>
      String((field as { name?: string }).name ?? ''),
    ) ?? [],
  );
  assert.ok(productPageNames.has('items_table'));
  assert.ok(Array.isArray(runtime.assembled.templateInput.items_table));
  assert.equal((runtime.assembled.templateInput.items_table as string[][]).length, 4);
  assert.deepEqual((runtime.assembled.templateInput.items_table as string[][])[0], [
    '1',
    'Product item 1',
    '1',
    'EA',
    'THB 1,200.00',
    'THB 0.00',
    'THB 1,200.00',
  ]);
});
