/**
 * 템플릿 기반 PPTX 생성기 - 템플릿과 데이터를 결합하여 PPTX 생성
 */

const fs = require('fs').promises;
const path = require('path');
const PptxGenJS = require('pptxgenjs');

// 템플릿 변수 처리 엔진
class TemplateEngine {
  constructor(data) {
    this.data = data;
  }

  /**
   * 템플릿 변수 치환
   */
  resolve(template) {
    if (typeof template === 'string') {
      return this.resolveString(template);
    } else if (Array.isArray(template)) {
      return template.map(item => this.resolve(item));
    } else if (typeof template === 'object' && template !== null) {
      const result = {};
      for (const [key, value] of Object.entries(template)) {
        result[key] = this.resolve(value);
      }
      return result;
    }
    return template;
  }

  /**
   * 문자열 템플릿 변수 치환
   */
  resolveString(template) {
    return template.replace(/\{\{([^}]+)\}\}/g, (match, path) => {
      const value = this.getNestedValue(this.data, path.trim());
      return value !== undefined ? value : match;
    });
  }

  /**
   * 중첩 객체 값 추출
   */
  getNestedValue(obj, path) {
    return path.split('.').reduce((current, key) => {
      return current && current[key] !== undefined ? current[key] : undefined;
    }, obj);
  }

  /**
   * 숫자 포맷팅
   */
  formatNumber(value, format) {
    if (format === 'currency') {
      return '₩' + value.toLocaleString();
    }
    return value.toString();
  }

  /**
   * 날짜 포맷팅
   */
  formatDate(value, format = 'YYYY-MM-DD') {
    const date = new Date(value);
    return date.toISOString().split('T')[0];
  }
}

// 템플릿 기반 PPTX 생성기
class TemplatePPTXGenerator {
  constructor() {
    this.pptx = new PptxGenJS();
    this.pptx.layout = 'LAYOUT_16x9';
  }

  /**
   * 템플릿을 기반으로 PPTX 생성
   */
  async generateFromTemplate(templatePath, dataPath) {
    console.log('📊 템플릿 기반 PPTX 생성 중...');

    // 템플릿과 데이터 로드
    const template = await this.loadTemplate(templatePath);
    const data = await this.loadData(dataPath);

    // 템플릿 엔진 초기화
    const engine = new TemplateEngine(data);

    // 색상 및 스타일 준비
    const resolvedStyles = engine.resolve(template.styles);
    this.colors = resolvedStyles.colors;
    this.fonts = resolvedStyles.fonts;

    // 각 슬라이드 생성
    for (const slideTemplate of template.slides) {
      await this.createSlideFromTemplate(slideTemplate, engine);
    }

    console.log(`✅ 템플릿 기반 PPTX 생성 완료: ${template.slides.length}개 슬라이드`);
    return this.pptx;
  }

  /**
   * 템플릿 파일 로드
   */
  async loadTemplate(templatePath) {
    const content = await fs.readFile(templatePath, 'utf8');
    return JSON.parse(content);
  }

  /**
   * 데이터 파일 로드
   */
  async loadData(dataPath) {
    const content = await fs.readFile(dataPath, 'utf8');
    return JSON.parse(content);
  }

  /**
   * 슬라이드 템플릿을 기반으로 슬라이드 생성
   */
  async createSlideFromTemplate(slideTemplate, engine) {
    const slide = this.pptx.addSlide();

    console.log(`📄 슬라이드 ${slideTemplate.slideNumber}: ${slideTemplate.name}`);

    // 각 요소 생성
    for (const element of slideTemplate.elements) {
      await this.createElement(slide, element, engine);
    }
  }

  /**
   * 요소 생성
   */
  async createElement(slide, element, engine) {
    const resolvedElement = engine.resolve(element);

    switch (element.type) {
      case 'background':
        this.createBackground(slide, resolvedElement);
        break;

      case 'text':
        this.createText(slide, resolvedElement);
        break;

      case 'shape':
        this.createShape(slide, resolvedElement);
        break;

      case 'table':
        this.createTable(slide, resolvedElement, engine);
        break;

      case 'buttonGroup':
        this.createButtonGroup(slide, resolvedElement);
        break;

      case 'infoSection':
        this.createInfoSection(slide, resolvedElement, engine);
        break;

      case 'dynamicStats':
        this.createDynamicStats(slide, resolvedElement, engine);
        break;

      default:
        console.log(`⚠️ 미지원 요소 타입: ${element.type}`);
    }
  }

  /**
   * 배경 생성
   */
  createBackground(slide, element) {
    slide.background = { color: element.style.color };
  }

  /**
   * 텍스트 생성
   */
  createText(slide, element) {
    const options = {
      x: element.position.x,
      y: element.position.y,
      w: element.position.w,
      h: element.position.h,
      ...element.style
    };

    slide.addText(element.content || element.placeholder || '', options);
  }

  /**
   * 도형 생성
   */
  createShape(slide, element) {
    const options = {
      x: element.position.x,
      y: element.position.y,
      w: element.position.w,
      h: element.position.h,
      ...element.style
    };

    slide.addShape(element.shapeType || 'rect', options);
  }

  /**
   * 테이블 생성
   */
  createTable(slide, element, engine) {
    let tableData = [];

    // 헤더 추가
    if (element.headers) {
      tableData.push(element.headers);
      if (element.subHeaders) {
        tableData.push(element.subHeaders);
      }
    }

    // 데이터 소스에서 행 생성
    if (element.dataSource) {
      const sourceData = engine.getNestedValue(engine.data, element.dataSource);
      if (Array.isArray(sourceData)) {
        sourceData.forEach((item, index) => {
          const row = this.generateTableRow(element, item, index, engine);
          tableData.push(row);
        });
      }
    }

    const options = {
      x: element.position.x,
      y: element.position.y,
      w: element.position.w,
      h: element.position.h,
      border: { pt: 1, color: '757575' },
      fontSize: 10,
      margin: 0.1,
      ...element.style
    };

    slide.addTable(tableData, options);
  }

  /**
   * 테이블 행 생성
   */
  generateTableRow(element, item, index, engine) {
    if (element.template === 'detailItemLayout') {
      return [
        (index + 1).toString(),
        item.name || '',
        item.product || '',
        item.width ? item.width.toLocaleString() : '',
        item.height ? item.height.toLocaleString() : '',
        item.quantity ? item.quantity.toString() : '',
        item.unit || '',
        item.materialCost ? engine.formatNumber(item.materialCost, 'currency') : '',
        item.materialCost && item.quantity ?
          engine.formatNumber(item.materialCost * item.quantity, 'currency') : '',
        item.laborCost ? engine.formatNumber(item.laborCost, 'currency') : '',
        item.laborCost && item.quantity ?
          engine.formatNumber(item.laborCost * item.quantity, 'currency') : '',
        item.totalCost ? engine.formatNumber(item.totalCost, 'currency') : '',
        item.totalCost && item.quantity ?
          engine.formatNumber(item.totalCost * item.quantity, 'currency') : '',
        item.memo || ''
      ];
    }

    // 기본 행 생성
    return Object.values(item);
  }

  /**
   * 버튼 그룹 생성
   */
  createButtonGroup(slide, element) {
    element.buttons.forEach((button, index) => {
      const xPos = element.position.x + index * 1.5;

      // 버튼 배경
      slide.addShape('rect', {
        x: xPos,
        y: element.position.y,
        w: 1.3,
        h: element.position.h,
        fill: { color: this.colors.primary },
        line: { color: this.colors.primary, width: 1 }
      });

      // 버튼 텍스트
      slide.addText(button.text, {
        x: xPos,
        y: element.position.y,
        w: 1.3,
        h: element.position.h,
        fontSize: 12,
        bold: true,
        color: 'FFFFFF',
        align: 'center'
      });
    });
  }

  /**
   * 정보 섹션 생성
   */
  createInfoSection(slide, element, engine) {
    // 섹션 배경
    slide.addShape('rect', {
      x: element.position.x,
      y: element.position.y,
      w: element.position.w,
      h: element.position.h,
      fill: { color: 'FFFFFF' },
      line: { color: 'CCCCCC', width: 1 }
    });

    // 섹션 제목
    slide.addText(element.title, {
      x: element.position.x + 0.2,
      y: element.position.y + 0.2,
      w: element.position.w - 0.4,
      h: 0.4,
      fontSize: 14,
      bold: true,
      color: '333333'
    });

    // 필드들
    element.fields.forEach((field, index) => {
      const row = Math.floor(index / 2);
      const col = index % 2;
      const xPos = element.position.x + 0.5 + col * 4;
      const yPos = element.position.y + 0.8 + row * 0.6;

      const value = engine.getNestedValue(engine.data, field.field);
      const formattedValue = field.format === 'currency' ?
        engine.formatNumber(value, 'currency') : value;

      slide.addText(`${field.label}: ${formattedValue || ''}`, {
        x: xPos,
        y: yPos,
        w: 3.5,
        h: 0.4,
        fontSize: 11,
        color: '333333'
      });
    });
  }

  /**
   * 동적 통계 박스 생성
   */
  createDynamicStats(slide, element, engine) {
    const statsData = engine.getNestedValue(engine.data, element.dataSource) || [
      { label: '전체 견적', value: '9', color: this.colors.primary },
      { label: '견적대기', value: '5', color: 'CC0000' },
      { label: '견적완료', value: '4', color: '008000' }
    ];

    statsData.forEach((stat, index) => {
      const xPos = element.position.x + index * 2;

      // 통계 박스
      slide.addShape('rect', {
        x: xPos,
        y: element.position.y,
        w: element.template.width,
        h: element.position.h,
        fill: { color: 'FFFFFF' },
        line: { color: 'CCCCCC', width: 1 }
      });

      // 통계 값
      slide.addText(stat.value, {
        x: xPos,
        y: element.position.y + 0.2,
        w: element.template.width,
        h: 0.8,
        fontSize: 24,
        bold: true,
        color: stat.color,
        align: 'center'
      });

      // 통계 라벨
      slide.addText(stat.label, {
        x: xPos,
        y: element.position.y + 0.8,
        w: element.template.width,
        h: 0.4,
        fontSize: 12,
        color: '333333',
        align: 'center'
      });
    });
  }
}

// 메인 실행 함수
async function generateFromTemplate(templatePath, dataPath, outputPath) {
  try {
    console.log('🚀 템플릿 기반 PPTX 생성 시작');
    console.log(`📋 템플릿: ${templatePath}`);
    console.log(`📊 데이터: ${dataPath}`);
    console.log(`📄 출력: ${outputPath}`);

    const generator = new TemplatePPTXGenerator();
    const pptx = await generator.generateFromTemplate(templatePath, dataPath);

    // 파일 저장
    await pptx.writeFile({ fileName: outputPath });
    console.log('✅ 템플릿 기반 PPTX 생성 완료!');

    return outputPath;

  } catch (error) {
    console.error('❌ 생성 실패:', error.message);
    throw error;
  }
}

// 명령행 인수 처리
async function main() {
  const args = process.argv.slice(2);
  const templateFlag = args.find(arg => arg.startsWith('--template='));
  const dataFlag = args.find(arg => arg.startsWith('--data='));
  const outputFlag = args.find(arg => arg.startsWith('--output='));

  const templatePath = templateFlag ? templateFlag.split('=')[1] : 'templates/sam_estimate_template.json';
  const dataPath = dataFlag ? dataFlag.split('=')[1] : 'data/sample_estimate_data.json';
  const outputPath = outputFlag ? outputFlag.split('=')[1] : 'pptx/template_generated.pptx';

  // 출력 디렉토리 생성
  await fs.mkdir(path.dirname(outputPath), { recursive: true });

  await generateFromTemplate(templatePath, dataPath, outputPath);
}

// 직접 실행시
if (require.main === module) {
  main().catch(console.error);
}

module.exports = { generateFromTemplate, TemplatePPTXGenerator, TemplateEngine };