const PurchaseRequestModel = require('../models/purchaseRequestModel');
const PurchaseModel = require('../models/purchaseModel');
const { saveBase64Image } = require('../services/imageUploadService');
const logger = require('../utils/logger');
const notifyHelper = require('../../../shared/utils/notifyHelper');
const koreanSearch = require('../utils/koreanSearch');

const PurchaseRequestController = {
  // 구매신청 목록
  getAll: async (req, res) => {
    try {
      const { status, category, from_date, to_date, batch_id } = req.query;
      const isAdmin = req.user && ['admin', 'system'].includes(req.user.access_level);
      const filters = { status, category, from_date, to_date, batch_id };
      if (!isAdmin) filters.requester_id = req.user.id;
      const rows = await PurchaseRequestModel.getAll(filters);
      res.json({ success: true, data: rows });
    } catch (err) {
      logger.error('PurchaseRequest getAll error:', err);
      res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
    }
  },

  // 구매신청 상세
  getById: async (req, res) => {
    try {
      const row = await PurchaseRequestModel.getById(req.params.id);
      if (!row) return res.status(404).json({ success: false, message: '신청 건을 찾을 수 없습니다.' });
      res.json({ success: true, data: row });
    } catch (err) {
      logger.error('PurchaseRequest getById error:', err);
      res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
    }
  },

  // 구매신청 생성
  create: async (req, res) => {
    try {
      const { item_id, custom_item_name, custom_category, quantity, notes, photo } = req.body;

      // item_id 또는 custom_item_name 중 하나 필수
      if (!item_id && !custom_item_name) {
        return res.status(400).json({ success: false, message: '소모품을 선택하거나 품목명을 입력해주세요.' });
      }
      if (!quantity || quantity < 1) {
        return res.status(400).json({ success: false, message: '수량은 1 이상이어야 합니다.' });
      }
      if (!item_id && custom_item_name && !custom_category) {
        return res.status(400).json({ success: false, message: '직접 입력 시 분류를 선택해주세요.' });
      }

      // 사진 업로드
      let photo_path = null;
      if (photo) {
        photo_path = await saveBase64Image(photo, 'pr', 'purchase_requests');
      }

      const request = await PurchaseRequestModel.create({
        item_id: item_id || null,
        custom_item_name: custom_item_name || null,
        custom_category: custom_category || null,
        quantity,
        requester_id: req.user.id,
        request_date: new Date().toISOString().substring(0, 10),
        notes,
        photo_path
      });
      res.status(201).json({ success: true, data: request, message: '구매신청이 등록되었습니다.' });
    } catch (err) {
      logger.error('PurchaseRequest create error:', err);
      res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
    }
  },

  // 보류 처리 (admin)
  hold: async (req, res) => {
    try {
      const { hold_reason } = req.body;
      const request = await PurchaseRequestModel.hold(req.params.id, hold_reason);
      if (!request) return res.status(404).json({ success: false, message: '신청 건을 찾을 수 없습니다.' });
      res.json({ success: true, data: request, message: '보류 처리되었습니다.' });
    } catch (err) {
      logger.error('PurchaseRequest hold error:', err);
      res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
    }
  },

  // pending으로 되돌리기 (admin)
  revert: async (req, res) => {
    try {
      const request = await PurchaseRequestModel.revertToPending(req.params.id);
      if (!request) return res.status(404).json({ success: false, message: '신청 건을 찾을 수 없습니다.' });
      res.json({ success: true, data: request, message: '대기 상태로 되돌렸습니다.' });
    } catch (err) {
      logger.error('PurchaseRequest revert error:', err);
      res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
    }
  },

  // 삭제 (본인 + pending만)
  delete: async (req, res) => {
    try {
      const existing = await PurchaseRequestModel.getById(req.params.id);
      if (!existing) return res.status(404).json({ success: false, message: '신청 건을 찾을 수 없습니다.' });
      const isAdmin = req.user && ['admin', 'system'].includes(req.user.access_level);
      if (!isAdmin && existing.requester_id !== req.user.id) {
        return res.status(403).json({ success: false, message: '본인의 신청만 삭제할 수 있습니다.' });
      }
      const deleted = await PurchaseRequestModel.delete(req.params.id);
      if (!deleted) return res.status(400).json({ success: false, message: '대기 상태의 신청만 삭제할 수 있습니다.' });
      res.json({ success: true, message: '삭제되었습니다.' });
    } catch (err) {
      logger.error('PurchaseRequest delete error:', err);
      res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
    }
  },

  // 품목 등록 + 신청 동시 처리 (단일 트랜잭션)
  registerAndRequest: async (req, res) => {
    const { getDb } = require('../dbPool');
    let conn;
    try {
      const { item_name, spec, maker, category, quantity, notes, photo } = req.body;
      if (!item_name || !item_name.trim()) {
        return res.status(400).json({ success: false, message: '품목명을 입력해주세요.' });
      }
      if (!quantity || quantity < 1) {
        return res.status(400).json({ success: false, message: '수량은 1 이상이어야 합니다.' });
      }

      const db = await getDb();
      conn = await db.getConnection();
      await conn.beginTransaction();

      // 1. 소모품 마스터 등록 (중복 확인)
      const [existing] = await conn.query(
        `SELECT item_id FROM consumable_items
         WHERE item_name = ? AND (spec = ? OR (spec IS NULL AND ? IS NULL))
           AND (maker = ? OR (maker IS NULL AND ? IS NULL))`,
        [item_name.trim(), spec || null, spec || null, maker || null, maker || null]
      );

      let itemId;
      if (existing.length > 0) {
        itemId = existing[0].item_id;
      } else {
        const [insertResult] = await conn.query(
          `INSERT INTO consumable_items (item_name, spec, maker, category, is_active) VALUES (?, ?, ?, ?, 1)`,
          [item_name.trim(), spec || null, maker || null, category || 'consumable']
        );
        itemId = insertResult.insertId;
      }

      // 2. 사진 업로드 (트랜잭션 외부 — 파일 저장은 DB 롤백 불가이므로 마지막에)
      let photo_path = null;
      if (photo) {
        photo_path = await saveBase64Image(photo, 'pr', 'purchase_requests');
      }

      // 3. 구매 신청 생성
      const [reqResult] = await conn.query(
        `INSERT INTO purchase_requests (item_id, quantity, requester_id, request_date, notes, photo_path)
         VALUES (?, ?, ?, CURDATE(), ?, ?)`,
        [itemId, quantity, req.user.id, notes || null, photo_path]
      );

      await conn.commit();

      // 검색 캐시 무효화
      koreanSearch.clearCache();

      const request = await PurchaseRequestModel.getById(reqResult.insertId);
      res.status(201).json({ success: true, data: request, message: '품목 등록 및 신청이 완료되었습니다.' });
    } catch (err) {
      if (conn) await conn.rollback().catch(() => {});
      logger.error('registerAndRequest error:', err);
      res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
    } finally {
      if (conn) conn.release();
    }
  },

  // 일괄 신청 (장바구니, 트랜잭션)
  bulkCreate: async (req, res) => {
    const { getDb } = require('../dbPool');
    let conn;
    try {
      const { items, photo } = req.body;
      if (!items || !Array.isArray(items) || items.length === 0) {
        return res.status(400).json({ success: false, message: '신청할 품목을 선택해주세요.' });
      }
      for (const item of items) {
        if (!item.item_id && !item.item_name) {
          return res.status(400).json({ success: false, message: '품목 정보가 올바르지 않습니다.' });
        }
        if (!item.quantity || item.quantity < 1) {
          return res.status(400).json({ success: false, message: '수량은 1 이상이어야 합니다.' });
        }
      }

      // 사진 업로드 (트랜잭션 밖 — 파일은 롤백 불가)
      let photo_path = null;
      if (photo) {
        photo_path = await saveBase64Image(photo, 'pr', 'purchase_requests');
      }

      const db = await getDb();
      conn = await db.getConnection();
      await conn.beginTransaction();

      const createdIds = [];
      let newItemRegistered = false;

      for (const item of items) {
        let itemId = item.item_id || null;

        // 신규 품목 등록 (is_new)
        if (item.is_new && item.item_name) {
          const [existing] = await conn.query(
            `SELECT item_id FROM consumable_items
             WHERE item_name = ? AND (spec = ? OR (spec IS NULL AND ? IS NULL))
               AND (maker = ? OR (maker IS NULL AND ? IS NULL))`,
            [item.item_name.trim(), item.spec || null, item.spec || null, item.maker || null, item.maker || null]
          );
          if (existing.length > 0) {
            itemId = existing[0].item_id;
          } else {
            // 신규 품목 사진 저장 (마스터에)
            let itemPhotoPath = null;
            if (item.item_photo) {
              itemPhotoPath = await saveBase64Image(item.item_photo, 'item', 'consumables');
            }
            const [ins] = await conn.query(
              `INSERT INTO consumable_items (item_name, spec, maker, category, photo_path, is_active) VALUES (?, ?, ?, ?, ?, 1)`,
              [item.item_name.trim(), item.spec || null, item.maker || null, item.category || 'consumable', itemPhotoPath]
            );
            itemId = ins.insertId;
            newItemRegistered = true;
          }
        }

        // purchase_request 생성
        const [result] = await conn.query(
          `INSERT INTO purchase_requests (item_id, custom_item_name, custom_category, quantity, requester_id, request_date, notes, photo_path)
           VALUES (?, ?, ?, ?, ?, CURDATE(), ?, ?)`,
          [itemId, item.is_new && !itemId ? item.item_name : null, item.is_new && !itemId ? item.category : null,
           item.quantity, req.user.id, item.notes || null, photo_path]
        );
        createdIds.push(result.insertId);
      }

      await conn.commit();
      if (newItemRegistered) koreanSearch.clearCache();

      res.status(201).json({
        success: true,
        data: { request_ids: createdIds, count: createdIds.length },
        message: `${createdIds.length}건의 소모품 신청이 등록되었습니다.`
      });
    } catch (err) {
      if (conn) await conn.rollback().catch(() => {});
      logger.error('bulkCreate error:', err);
      res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
    } finally {
      if (conn) conn.release();
    }
  },

  // 품목 마스터 사진 등록/업데이트
  updateItemPhoto: async (req, res) => {
    try {
      const { photo } = req.body;
      if (!photo) return res.status(400).json({ success: false, message: '사진을 첨부해주세요.' });
      const itemPhotoPath = await saveBase64Image(photo, 'item', 'consumables');
      if (!itemPhotoPath) return res.status(500).json({ success: false, message: '사진 저장에 실패했습니다.' });

      const { getDb } = require('../dbPool');
      const db = await getDb();
      await db.query('UPDATE consumable_items SET photo_path = ? WHERE item_id = ?', [itemPhotoPath, req.params.id]);
      koreanSearch.clearCache();
      res.json({ success: true, data: { photo_path: itemPhotoPath }, message: '품목 사진이 등록되었습니다.' });
    } catch (err) {
      logger.error('updateItemPhoto error:', err);
      res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
    }
  },

  // 스마트 검색 (초성 + 별칭 + substring)
  search: async (req, res) => {
    try {
      const { q } = req.query;
      const results = await koreanSearch.search(q || '');
      res.json({ success: true, data: results });
    } catch (err) {
      logger.error('PurchaseRequest search error:', err);
      res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
    }
  },

  // 소모품 목록 (select용)
  getConsumableItems: async (req, res) => {
    try {
      const items = await PurchaseModel.getConsumableItems();
      res.json({ success: true, data: items });
    } catch (err) {
      logger.error('ConsumableItems get error:', err);
      res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
    }
  },

  // 업체 목록 (select용)
  getVendors: async (req, res) => {
    try {
      const vendors = await PurchaseModel.getVendors();
      res.json({ success: true, data: vendors });
    } catch (err) {
      logger.error('Vendors get error:', err);
      res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
    }
  },

  // 내 신청 목록 (모바일용, 페이지네이션)
  getMyRequests: async (req, res) => {
    try {
      const page = parseInt(req.query.page) || 1;
      const limit = parseInt(req.query.limit) || 20;
      const { status } = req.query;
      const result = await PurchaseRequestModel.getMyRequests(req.user.id, { page, limit, status });
      res.json({ success: true, ...result });
    } catch (err) {
      logger.error('PurchaseRequest getMyRequests error:', err);
      res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
    }
  },

  // 개별 입고 처리 (admin)
  receive: async (req, res) => {
    try {
      const existing = await PurchaseRequestModel.getById(req.params.id);
      if (!existing) return res.status(404).json({ success: false, message: '신청 건을 찾을 수 없습니다.' });
      if (existing.status !== 'purchased') {
        return res.status(400).json({ success: false, message: '구매완료 상태의 신청만 입고 처리할 수 있습니다.' });
      }

      const { received_location, photo } = req.body;
      let receivedPhotoPath = null;
      if (photo) {
        receivedPhotoPath = await saveBase64Image(photo, 'received', 'purchase_received');
      }

      const updated = await PurchaseRequestModel.receive(req.params.id, {
        receivedPhotoPath,
        receivedLocation: received_location || null,
        receivedBy: req.user.id
      });

      // batch 내 전체 입고 완료 시 batch.status 자동 전환
      if (existing.batch_id) {
        const allReceived = await PurchaseRequestModel.checkBatchAllReceived(existing.batch_id);
        if (allReceived) {
          const { getDb } = require('../dbPool');
          const db = await getDb();
          await db.query(
            `UPDATE purchase_batches SET status = 'received', received_at = NOW(), received_by = ? WHERE batch_id = ?`,
            [req.user.id, existing.batch_id]
          );
        }
      }

      // 신청자에게 입고 알림
      notifyHelper.send({
        type: 'purchase',
        title: '소모품 입고 완료',
        message: `${existing.item_name || existing.custom_item_name} 입고 완료${received_location ? '. 보관위치: ' + received_location : ''}`,
        link_url: '/pages/purchase/request-mobile.html?view=' + req.params.id,
        target_user_ids: [existing.requester_id],
        created_by: req.user.id
      }).catch(() => {});

      res.json({ success: true, data: updated, message: '입고 처리가 완료되었습니다.' });
    } catch (err) {
      logger.error('PurchaseRequest receive error:', err);
      res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
    }
  },

  // 구매 취소 (purchased → cancelled)
  cancel: async (req, res) => {
    try {
      const existing = await PurchaseRequestModel.getById(req.params.id);
      if (!existing) return res.status(404).json({ success: false, message: '신청 건을 찾을 수 없습니다.' });
      if (existing.status !== 'purchased') {
        return res.status(400).json({ success: false, message: '구매완료 상태의 신청만 취소할 수 있습니다.' });
      }
      const { cancel_reason } = req.body;
      const updated = await PurchaseRequestModel.cancelPurchase(req.params.id, {
        cancelledBy: req.user.id,
        cancelReason: cancel_reason
      });
      res.json({ success: true, data: updated, message: '구매가 취소되었습니다.' });
    } catch (err) {
      logger.error('PurchaseRequest cancel error:', err);
      res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
    }
  },

  // 반품 (received → returned)
  returnItem: async (req, res) => {
    try {
      const existing = await PurchaseRequestModel.getById(req.params.id);
      if (!existing) return res.status(404).json({ success: false, message: '신청 건을 찾을 수 없습니다.' });
      if (existing.status !== 'received') {
        return res.status(400).json({ success: false, message: '입고완료 상태의 신청만 반품할 수 있습니다.' });
      }
      const { cancel_reason } = req.body;
      const updated = await PurchaseRequestModel.returnItem(req.params.id, {
        cancelledBy: req.user.id,
        cancelReason: cancel_reason
      });

      // 신청자에게 반품 알림
      notifyHelper.send({
        type: 'purchase',
        title: '소모품 반품 처리',
        message: `${existing.item_name || existing.custom_item_name} 반품 처리되었습니다.${cancel_reason ? ' 사유: ' + cancel_reason : ''}`,
        link_url: '/pages/purchase/request-mobile.html?view=' + req.params.id,
        target_user_ids: [existing.requester_id],
        created_by: req.user.id
      }).catch(() => {});

      res.json({ success: true, data: updated, message: '반품 처리되었습니다.' });
    } catch (err) {
      logger.error('PurchaseRequest return error:', err);
      res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
    }
  },

  // 취소 → 대기로 되돌리기
  revertCancel: async (req, res) => {
    try {
      const existing = await PurchaseRequestModel.getById(req.params.id);
      if (!existing) return res.status(404).json({ success: false, message: '신청 건을 찾을 수 없습니다.' });
      if (existing.status !== 'cancelled') {
        return res.status(400).json({ success: false, message: '취소 상태의 신청만 되돌릴 수 있습니다.' });
      }
      const updated = await PurchaseRequestModel.revertCancel(req.params.id);
      res.json({ success: true, data: updated, message: '대기 상태로 되돌렸습니다.' });
    } catch (err) {
      logger.error('PurchaseRequest revertCancel error:', err);
      res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
    }
  }
};

module.exports = PurchaseRequestController;
