package com.writeoff.module.setting.invoiceprofile.service;

import com.writeoff.common.api.PageResult;
import com.writeoff.common.exception.BusinessException;
import com.writeoff.module.setting.invoiceprofile.dto.CreateInvoiceProfileRequest;
import com.writeoff.module.setting.invoiceprofile.dto.UpdateInvoiceProfileRequest;
import com.writeoff.module.setting.invoiceprofile.model.InvoiceProfileInfo;
import com.writeoff.security.AuthContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class InvoiceProfileService {
    private final JdbcTemplate jdbcTemplate;

    private static final RowMapper<InvoiceProfileInfo> ROW_MAPPER = (rs, n) -> new InvoiceProfileInfo(
            rs.getLong("id"),
            rs.getString("company_name"),
            rs.getString("tax_no"),
            rs.getString("bank_name"),
            rs.getString("account_no"),
            rs.getString("address"),
            rs.getString("phone"),
            rs.getObject("default_project_id") == null ? null : rs.getLong("default_project_id"),
            rs.getString("status")
    );

    public InvoiceProfileService(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public PageResult<InvoiceProfileInfo> list() {
        List<InvoiceProfileInfo> list = jdbcTemplate.query(
                "SELECT * FROM invoice_profile WHERE tenant_id=? AND is_deleted=0 ORDER BY id DESC",
                ROW_MAPPER,
                tenantId()
        );
        return new PageResult<InvoiceProfileInfo>(list, list.size(), 1, 200);
    }

    @Transactional(rollbackFor = Exception.class)
    public InvoiceProfileInfo create(CreateInvoiceProfileRequest request) {
        assertUnique(request.getTaxNo(), request.getAccountNo(), null);
        String status = normalizeStatus(request.getStatus());
        jdbcTemplate.update(
                "INSERT INTO invoice_profile (tenant_id, company_name, tax_no, bank_name, account_no, address, phone, default_project_id, status, created_by, updated_by) " +
                        "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
                tenantId(),
                request.getCompanyName(),
                request.getTaxNo(),
                request.getBankName(),
                request.getAccountNo(),
                request.getAddress(),
                request.getPhone(),
                request.getDefaultProjectId(),
                status,
                safeUserId(),
                safeUserId()
        );
        Long id = jdbcTemplate.queryForObject("SELECT IFNULL(MAX(id),0) FROM invoice_profile WHERE tenant_id=?", Long.class, tenantId());
        return findById(id == null ? 0L : id);
    }

    @Transactional(rollbackFor = Exception.class)
    public InvoiceProfileInfo update(Long id, UpdateInvoiceProfileRequest request) {
        assertExists(id);
        assertUnique(request.getTaxNo(), request.getAccountNo(), id);
        String status = normalizeStatus(request.getStatus());
        jdbcTemplate.update(
                "UPDATE invoice_profile SET company_name=?, tax_no=?, bank_name=?, account_no=?, address=?, phone=?, default_project_id=?, status=?, updated_at=CURRENT_TIMESTAMP, updated_by=? " +
                        "WHERE tenant_id=? AND id=?",
                request.getCompanyName(),
                request.getTaxNo(),
                request.getBankName(),
                request.getAccountNo(),
                request.getAddress(),
                request.getPhone(),
                request.getDefaultProjectId(),
                status,
                safeUserId(),
                tenantId(),
                id
        );
        return findById(id);
    }

    public InvoiceProfileInfo enable(Long id) {
        return updateStatus(id, "ENABLED");
    }

    public InvoiceProfileInfo disable(Long id) {
        return updateStatus(id, "DISABLED");
    }

    private InvoiceProfileInfo updateStatus(Long id, String status) {
        assertExists(id);
        jdbcTemplate.update(
                "UPDATE invoice_profile SET status=?, updated_at=CURRENT_TIMESTAMP, updated_by=? WHERE tenant_id=? AND id=?",
                status,
                safeUserId(),
                tenantId(),
                id
        );
        return findById(id);
    }

    private void assertUnique(String taxNo, String accountNo, Long selfId) {
        if (taxNo == null || taxNo.trim().isEmpty() || accountNo == null || accountNo.trim().isEmpty()) {
            throw new BusinessException(10001, "税号和账号不能为空");
        }
        Integer count = jdbcTemplate.queryForObject(
                "SELECT COUNT(1) FROM invoice_profile WHERE tenant_id=? AND tax_no=? AND account_no=? AND is_deleted=0 AND (? IS NULL OR id<>?)",
                Integer.class,
                tenantId(),
                taxNo.trim(),
                accountNo.trim(),
                selfId,
                selfId
        );
        if (count != null && count > 0) {
            throw new BusinessException(10001, "同税号与账号的发票抬头已存在");
        }
    }

    private InvoiceProfileInfo findById(Long id) {
        List<InvoiceProfileInfo> list = jdbcTemplate.query(
                "SELECT * FROM invoice_profile WHERE tenant_id=? AND id=? AND is_deleted=0",
                ROW_MAPPER,
                tenantId(),
                id
        );
        if (list.isEmpty()) {
            throw new BusinessException(10003, "发票抬头不存在");
        }
        return list.get(0);
    }

    private void assertExists(Long id) {
        Integer count = jdbcTemplate.queryForObject(
                "SELECT COUNT(1) FROM invoice_profile WHERE tenant_id=? AND id=? AND is_deleted=0",
                Integer.class,
                tenantId(),
                id
        );
        if (count == null || count == 0) {
            throw new BusinessException(10003, "发票抬头不存在");
        }
    }

    private String normalizeStatus(String status) {
        String val = status == null ? "ENABLED" : status.trim().toUpperCase();
        if (!"ENABLED".equals(val) && !"DISABLED".equals(val)) {
            throw new BusinessException(10001, "状态仅支持 ENABLED/DISABLED");
        }
        return val;
    }

    private Long safeUserId() {
        Long userId = AuthContext.userId();
        return userId == null ? 0L : userId;
    }

    private Long tenantId() {
        return AuthContext.requireTenantId();
    }
}
