package com.ruoyi.credit.controller;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.credit.domain.Contract;
import com.ruoyi.credit.service.IContractService;

/**
 * 合同管理API控制器
 *
 * 提供服务合同的创建、上传、确认、查询等RESTful API接口 支持线上合同创建和线下合同上传两种模式
 *
 * @author ruoyi
 * @date 2025-12-19
 */
@RestController
@RequestMapping("/api/credit/contracts")
public class ServiceContractController extends BaseController {

    @Autowired
    private IContractService contractService;

    /**
     * 在平台上创建服务合同
     *
     * 注意：合同状态和合同来源由后端自动管理，前端不得提供相关信息
     *
     * @param contractInfo 合同信息（不包含状态和来源字段）
     * @return 创建结果
     */
    @PreAuthorize("@ss.hasPermi('credit:contract:add')")
    @Log(title = "服务合同", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult createContract(@Validated @RequestBody Contract contractInfo) {
        try {
            // 安全措施：强制清除前端可能提供的状态信息
            contractInfo.setContractStatus(null);

            Contract contract = contractService.createContract(contractInfo);
            return success(contract);
        } catch (Exception e) {
            logger.error("创建合同失败", e);
            return error("创建合同失败: " + e.getMessage());
        }
    }

    /**
     * 上传已签署的线下合同
     *
     * 注意：合同状态由后端自动管理，前端不得提供相关信息
     *
     * @param contractFile 合同文件
     * @param securityCompanyName 安保公司名称
     * @param clientCompanyName 甲方单位名称
     * @param contractAmount 合同金额
     * @param contractTitle 合同标题
     * @param serviceStartDate 服务开始日期 (格式: yyyy-MM-dd)
     * @param serviceEndDate 服务结束日期 (格式: yyyy-MM-dd)
     * @return 上传结果
     */
    @PreAuthorize("@ss.hasPermi('credit:contract:upload')")
    @Log(title = "服务合同", businessType = BusinessType.INSERT)
    @PostMapping("/upload")
    public AjaxResult uploadSignedContract(
            @RequestParam("file") MultipartFile contractFile,
            @RequestParam("securityCompanyName") String securityCompanyName,
            @RequestParam("clientCompanyName") String clientCompanyName,
            @RequestParam("contractAmount") String contractAmount,
            @RequestParam("contractTitle") String contractTitle,
            @RequestParam("serviceStartDate") String serviceStartDate,
            @RequestParam("serviceEndDate") String serviceEndDate) {
        try {
            // 参数验证
            if (contractFile == null || contractFile.isEmpty()) {
                return error("合同文件不能为空");
            }
            
            if (securityCompanyName == null || securityCompanyName.trim().isEmpty()) {
                return error("安保公司名称不能为空");
            }
            
            if (clientCompanyName == null || clientCompanyName.trim().isEmpty()) {
                return error("甲方单位名称不能为空");
            }
            
            if (contractTitle == null || contractTitle.trim().isEmpty()) {
                return error("合同标题不能为空");
            }
            
            if (contractAmount == null || contractAmount.trim().isEmpty()) {
                return error("合同金额不能为空");
            }
            
            if (serviceStartDate == null || serviceStartDate.trim().isEmpty()) {
                return error("服务开始日期不能为空");
            }
            
            if (serviceEndDate == null || serviceEndDate.trim().isEmpty()) {
                return error("服务结束日期不能为空");
            }

            // 构建合同基本信息
            Contract contractInfo = new Contract();
            contractInfo.setSecurityCompany(securityCompanyName.trim());
            contractInfo.setClientCompany(clientCompanyName.trim());
            contractInfo.setTitle(contractTitle.trim());
            contractInfo.setContractType("OFFLINE");

            // 安全措施：确保状态字段为空，由后端控制
            contractInfo.setContractStatus(null);

            // 解析金额
            contractInfo.setContractAmount(new java.math.BigDecimal(contractAmount.trim()));

            // 解析日期 (yyyy-MM-dd格式)
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            dateFormat.setLenient(false); // 严格模式
            contractInfo.setStartDate(dateFormat.parse(serviceStartDate.trim()));
            contractInfo.setEndDate(dateFormat.parse(serviceEndDate.trim()));
            
            // 验证日期逻辑
            if (contractInfo.getStartDate().after(contractInfo.getEndDate())) {
                return error("服务开始日期不能晚于结束日期");
            }

            Contract contract = contractService.uploadSignedContract(contractFile, contractInfo);
            return success(contract);
        } catch (ParseException e) {
            logger.error("日期格式解析失败", e);
            return error("日期格式错误，请使用yyyy-MM-dd格式: " + e.getMessage());
        } catch (NumberFormatException e) {
            logger.error("金额格式解析失败", e);
            return error("金额格式错误: " + e.getMessage());
        } catch (Exception e) {
            logger.error("上传合同失败", e);
            return error("上传合同失败: " + e.getMessage());
        }
    }

    /**
     * 确认合同
     *
     * @param id 合同ID
     * @param partyType 确认方类型 (SECURITY_COMPANY/CLIENT_COMPANY)
     * @return 确认结果
     */
    @PreAuthorize("@ss.hasPermi('credit:contract:confirm')")
    @Log(title = "服务合同", businessType = BusinessType.UPDATE)
    @PutMapping("/{id}/confirm")
    public AjaxResult confirmContract(@PathVariable("id") Long id,
            @RequestParam("partyType") String partyType) {
        try {
            // 参数验证
            if (id == null || id <= 0) {
                return error("合同ID无效");
            }
            
            if (partyType == null || partyType.trim().isEmpty()) {
                return error("确认方类型不能为空");
            }
            
            // 验证确认方类型
            if (!"SECURITY_COMPANY".equals(partyType) && !"CLIENT_COMPANY".equals(partyType)) {
                return error("确认方类型只能是SECURITY_COMPANY或CLIENT_COMPANY");
            }
            
            // 检查合同是否存在
            Contract contract = contractService.selectContractByContractId(id);
            if (contract == null) {
                return error("合同不存在");
            }

            boolean result = contractService.confirmContract(id, partyType);
            if (result) {
                return success("确认合同成功").put("contractId", id);
            } else {
                return error("确认合同失败");
            }
        } catch (Exception e) {
            logger.error("确认合同失败", e);
            return error("确认合同失败: " + e.getMessage());
        }
    }

    /**
     * 获取合同详情
     *
     * @param id 合同ID
     * @return 合同详情
     */
    @PreAuthorize("@ss.hasPermi('credit:contract:query')")
    @GetMapping("/{id}")
    public AjaxResult getContract(@PathVariable("id") Long id) {
        try {
            Contract contract = contractService.selectContractByContractId(id);
            if (contract != null) {
                return success(contract);
            } else {
                return error("合同不存在");
            }
        } catch (Exception e) {
            logger.error("查询合同失败", e);
            return error("查询合同失败: " + e.getMessage());
        }
    }

    /**
     * 查询合同列表
     *
     * @param contract 查询条件
     * @return 合同列表
     */
    @PreAuthorize("@ss.hasPermi('credit:contract:list')")
    @GetMapping
    public TableDataInfo getContractList(Contract contract) {
        try {
            startPage();
            List<Contract> list = contractService.selectContractList(contract);
            return getDataTable(list);
        } catch (Exception e) {
            logger.error("查询合同列表失败", e);
            return getDataTable(null);
        }
    }

    /**
     * 更新合同信息
     *
     * @param id 合同ID
     * @param contractInfo 合同信息
     * @return 更新结果
     */
    @PreAuthorize("@ss.hasPermi('credit:contract:edit')")
    @Log(title = "服务合同", businessType = BusinessType.UPDATE)
    @PutMapping("/{id}")
    public AjaxResult updateContract(@PathVariable("id") Long id,
            @Validated @RequestBody Contract contractInfo) {
        try {
            // 设置合同ID
            contractInfo.setContractId(id);

            // 安全措施：防止前端修改状态字段
            contractInfo.setContractStatus(null);

            boolean result = contractService.updateContract(contractInfo);
            if (result) {
                return success("更新合同成功").put("contractId", id);
            } else {
                return error("更新合同失败");
            }
        } catch (Exception e) {
            logger.error("更新合同失败", e);
            return error("更新合同失败: " + e.getMessage());
        }
    }

    /**
     * 更新合同状态
     *
     * 注意：此接口仅供内部系统调用，不允许前端直接修改状态
     *
     * @param id 合同ID
     * @param status 新状态
     * @return 更新结果
     */
    @PreAuthorize("@ss.hasPermi('credit:contract:edit')")
    @Log(title = "服务合同", businessType = BusinessType.UPDATE)
    @PutMapping("/{id}/status")
    public AjaxResult updateContractStatus(@PathVariable("id") Long id,
            @RequestParam("status") String status) {
        try {
            // 参数验证
            if (id == null || id <= 0) {
                return error("合同ID无效");
            }
            
            if (status == null || status.trim().isEmpty()) {
                return error("合同状态不能为空");
            }
            
            // 验证状态值的有效性
            String[] validStatuses = {"DRAFT", "PENDING", "CONFIRMED", "ACTIVE", "EXPIRED", "CANCELLED"};
            boolean isValidStatus = false;
            for (String validStatus : validStatuses) {
                if (validStatus.equals(status.trim())) {
                    isValidStatus = true;
                    break;
                }
            }
            if (!isValidStatus) {
                return error("无效的合同状态");
            }

            // 记录状态变更审计日志
            Contract oldContract = contractService.selectContractByContractId(id);
            if (oldContract == null) {
                return error("合同不存在");
            }

            boolean result = contractService.updateContractStatus(id, status.trim());

            // 记录状态变更审计日志
            if (result) {
                contractService.recordStatusChangeAudit(id, oldContract.getContractStatus(), status.trim(), "系统内部状态更新");
                // 返回合同ID
                return success("更新合同状态成功").put("contractId", id);
            }

            return error("更新合同状态失败");
        } catch (Exception e) {
            logger.error("更新合同状态失败", e);
            return error("更新合同状态失败: " + e.getMessage());
        }
    }

    /**
     * 删除合同
     *
     * @param ids 合同ID数组
     * @return 删除结果
     */
    @PreAuthorize("@ss.hasPermi('credit:contract:remove')")
    @Log(title = "服务合同", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult deleteContract(@PathVariable Long[] ids) {
        try {
            // 参数验证
            if (ids == null || ids.length == 0) {
                return error("合同ID不能为空");
            }
            
            // 验证每个ID的有效性
            for (Long id : ids) {
                if (id == null || id <= 0) {
                    return error("存在无效的合同ID");
                }
            }
            
            // 检查合同是否存在且可以删除
            for (Long id : ids) {
                Contract contract = contractService.selectContractByContractId(id);
                if (contract == null) {
                    return error("合同ID " + id + " 不存在");
                }
                
                // 检查合同状态，某些状态下不允许删除
                if ("ACTIVE".equals(contract.getContractStatus()) || "CONFIRMED".equals(contract.getContractStatus())) {
                    return error("合同ID " + id + " 状态为" + contract.getContractStatus() + "，不允许删除");
                }
            }

            int result = contractService.deleteContractByContractIds(ids);
            return toAjax(result);
        } catch (Exception e) {
            logger.error("删除合同失败", e);
            return error("删除合同失败: " + e.getMessage());
        }
    }

    /**
     * 验证合同数据
     *
     * @param id 合同ID
     * @param contractInfo 合同信息
     * @return 验证结果
     */
    @PreAuthorize("@ss.hasPermi('credit:contract:query')")
    @PostMapping("/{id}/validate")
    public AjaxResult validateContract(@PathVariable("id") Long id,
            @RequestBody Contract contractInfo) {
        try {
            // 参数验证
            if (id == null || id <= 0) {
                return error("合同ID无效");
            }
            
            if (contractInfo == null) {
                return error("合同信息不能为空");
            }
            
            // 检查合同是否存在
            Contract existingContract = contractService.selectContractByContractId(id);
            if (existingContract == null) {
                return error("合同不存在");
            }
            
            // 设置合同ID以便验证
            contractInfo.setContractId(id);

            Map<String, Object> result = contractService.validateContractData(contractInfo);
            return AjaxResult.success(result);
        } catch (Exception e) {
            logger.error("验证合同数据失败", e);
            return AjaxResult.error("验证合同数据失败: " + e.getMessage());
        }
    }

    /**
     * 下载合同文件
     *
     * @param id 合同ID
     * @param response HTTP响应
     */
    @PreAuthorize("@ss.hasPermi('credit:contract:query')")
    @GetMapping("/{id}/file")
    public void downloadContractFile(@PathVariable("id") Long id, HttpServletResponse response) {
        try {
            // 查询合同信息
            Contract contract = contractService.selectContractByContractId(id);
            if (contract == null) {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                return;
            }

            // 检查合同文件URL是否存在
            String fileUrl = contract.getFileUrl();
            if (fileUrl == null || fileUrl.trim().isEmpty()) {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                return;
            }

            // TODO: 实现文件下载逻辑
            // 这里需要根据实际的文件存储方式来实现
            // 例如：从本地文件系统、OSS、或其他存储服务下载文件
            
            response.setStatus(HttpServletResponse.SC_NOT_IMPLEMENTED);
            response.getWriter().write("文件下载功能待实现");
            
        } catch (Exception e) {
            logger.error("下载合同文件失败", e);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }

    /**
     * 从上传文件提取合同信息
     *
     * @param id 合同ID
     * @param contractFile 合同文件
     * @return 提取的信息
     */
    @PreAuthorize("@ss.hasPermi('credit:contract:edit')")
    @PostMapping("/{id}/extract-info")
    public AjaxResult extractContractInfo(@PathVariable("id") Long id,
            @RequestParam("file") MultipartFile contractFile) {
        try {
            // 参数验证
            if (id == null || id <= 0) {
                return error("合同ID无效");
            }
            
            if (contractFile == null || contractFile.isEmpty()) {
                return error("合同文件不能为空");
            }
            
            // 检查合同是否存在
            Contract contract = contractService.selectContractByContractId(id);
            if (contract == null) {
                return error("合同不存在");
            }
            
            // 验证文件类型
            String fileName = contractFile.getOriginalFilename();
            if (fileName == null || fileName.trim().isEmpty()) {
                return error("文件名不能为空");
            }
            
            String fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
            if (!"pdf".equals(fileExtension) && !"doc".equals(fileExtension) && !"docx".equals(fileExtension)) {
                return error("只支持PDF、DOC、DOCX格式的文件");
            }

            Map<String, Object> result = contractService.extractContractInfo(contractFile);
            return success(result);
        } catch (Exception e) {
            logger.error("提取合同信息失败", e);
            return error("提取合同信息失败: " + e.getMessage());
        }
    }

    /**
     * 导出合同数据
     *
     * @param response HTTP响应
     * @param contract 查询条件
     */
    @PreAuthorize("@ss.hasPermi('credit:contract:export')")
    @Log(title = "服务合同", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, Contract contract) {
        try {
            List<Contract> list = contractService.selectContractList(contract);
            ExcelUtil<Contract> util = new ExcelUtil<>(Contract.class);
            util.exportExcel(response, list, "服务合同数据");
        } catch (Exception e) {
            logger.error("导出合同数据失败", e);
        }
    }

    /**
     * 获取合同统计信息
     *
     * @return 统计信息
     */
    @PreAuthorize("@ss.hasPermi('credit:contract:query')")
    @GetMapping("/statistics")
    public AjaxResult getContractStatistics() {
        try {
            Map<String, Object> statistics = new java.util.HashMap<>();
            
            // 获取各状态合同数量
            statistics.put("draftCount", contractService.selectContractByStatus("DRAFT").size());
            statistics.put("pendingCount", contractService.selectContractByStatus("PENDING").size());
            statistics.put("confirmedCount", contractService.selectContractByStatus("CONFIRMED").size());
            statistics.put("activeCount", contractService.selectContractByStatus("ACTIVE").size());
            statistics.put("expiredCount", contractService.selectContractByStatus("EXPIRED").size());
            statistics.put("cancelledCount", contractService.selectContractByStatus("CANCELLED").size());
            
            // 获取即将到期的合同数量（30天内）
            statistics.put("expiringCount", contractService.selectExpiringContracts(30).size());
            
            return success(statistics);
        } catch (Exception e) {
            logger.error("获取合同统计信息失败", e);
            return error("获取合同统计信息失败: " + e.getMessage());
        }
    }

    /**
     * 获取即将到期的合同列表
     *
     * @param days 提前天数，默认30天
     * @return 即将到期的合同列表
     */
    @PreAuthorize("@ss.hasPermi('credit:contract:query')")
    @GetMapping("/expiring")
    public TableDataInfo getExpiringContracts(@RequestParam(value = "days", defaultValue = "30") int days) {
        try {
            if (days <= 0) {
                days = 30; // 默认30天
            }
            
            startPage();
            List<Contract> list = contractService.selectExpiringContracts(days);
            return getDataTable(list);
        } catch (Exception e) {
            logger.error("查询即将到期合同失败", e);
            return getDataTable(null);
        }
    }

    /**
     * 根据合同编号查询合同
     *
     * @param contractNumber 合同编号
     * @return 合同信息
     */
    @PreAuthorize("@ss.hasPermi('credit:contract:query')")
    @GetMapping("/number/{contractNumber}")
    public AjaxResult getContractByNumber(@PathVariable("contractNumber") String contractNumber) {
        try {
            if (contractNumber == null || contractNumber.trim().isEmpty()) {
                return error("合同编号不能为空");
            }
            
            Contract contract = contractService.selectContractByContractNumber(contractNumber.trim());
            if (contract != null) {
                return success(contract);
            } else {
                return error("合同不存在");
            }
        } catch (Exception e) {
            logger.error("根据合同编号查询合同失败", e);
            return error("查询合同失败: " + e.getMessage());
        }
    }
}
