package vehicle

import (
	"errors"
	"fmt"
	"time"
	"wails-app/internal/dao"
	"wails-app/internal/global"
	"wails-app/internal/model/vehicle/request"
	vehicleResponse "wails-app/internal/model/vehicle/response"
	ticketService "wails-app/internal/modules/digital-ticket/service"
	paymentService "wails-app/internal/modules/payment/service"

	"gorm.io/gorm"
)

type VehicleService struct{}

// buildPlateOrRfidQuery 按车牌或RFID查询，RFID为空时仅用车牌（避免 rfid_tag='' 匹配所有无标签车辆）
func buildPlateOrRfidQuery(db *gorm.DB, plateNumber, rfidTag string) *gorm.DB {
	if rfidTag != "" {
		return db.Where("plate_number = ? OR rfid_tag = ?", plateNumber, rfidTag)
	}
	return db.Where("plate_number = ?", plateNumber)
}

// CreateVehicle 创建车辆信息
func (s *VehicleService) CreateVehicle(req request.VehicleCreate) error {
	// 检查车牌号是否已存在
	var existingVehicle dao.Vehicle
	result := buildPlateOrRfidQuery(global.GVA_DB, req.PlateNumber, req.RFIDTag).First(&existingVehicle)
	if result.RowsAffected > 0 {
		return errors.New("车牌号已存在")
	}
	// 检查车辆类型是否存在
	var vehicleType dao.VehicleType
	result = global.GVA_DB.First(&vehicleType, req.VehicleTypeID)
	if result.RowsAffected == 0 {
		return errors.New("车辆类型不存在")
	}
	// 处理临时车辆的情况
	var ownerId *uint
	if req.OwnerId > 0 {
		ownerId = &req.OwnerId
	}
	vehicle := dao.Vehicle{
		PlateNumber:   req.PlateNumber,
		RFIDTag:       req.RFIDTag,
		VehicleTypeID: req.VehicleTypeID,
		VehicleBrand:  req.VehicleBrand,
		VehicleColor:  req.VehicleColor,
		OwnerId:       ownerId,
	}

	return global.GVA_DB.Create(&vehicle).Error
}

// UpdateVehicle 更新车辆信息
func (s *VehicleService) UpdateVehicle(req request.VehicleUpdate) error {
	var vehicle dao.Vehicle
	result := global.GVA_DB.First(&vehicle, req.ID)
	if result.RowsAffected == 0 {
		return errors.New("车辆不存在")
	}

	// 检查车牌号是否被其他车辆使用
	var existingVehicle dao.Vehicle
	result = buildPlateOrRfidQuery(global.GVA_DB, req.PlateNumber, req.RFIDTag).Where("id != ?", req.ID).First(&existingVehicle)
	fmt.Println("result", result.RowsAffected)
	if result.RowsAffected > 0 {
		return errors.New("车牌号已被其他车辆使用")
	}

	// 检查车辆类型是否存在
	var vehicleType dao.VehicleType
	result = global.GVA_DB.First(&vehicleType, req.VehicleTypeID)
	if result.RowsAffected == 0 {
		return errors.New("车辆类型不存在")
	}

	// 处理临时车辆的情况
	var ownerId *uint
	if req.OwnerId > 0 {
		ownerId = &req.OwnerId
	} else {
		ownerId = nil
	}
	err := global.GVA_DB.Model(&vehicle).Updates(map[string]interface{}{
		"plate_number":    req.PlateNumber,
		"rfid_tag":        req.RFIDTag,
		"vehicle_type_id": req.VehicleTypeID,
		"vehicle_brand":   req.VehicleBrand,
		"vehicle_color":   req.VehicleColor,
		"owner_id":        ownerId,
	}).Error

	return err
}

// GetVehicleByID 根据ID获取车辆信息
func (s *VehicleService) GetVehicleByID(id uint) (dao.Vehicle, error) {
	var vehicle dao.Vehicle
	result := global.GVA_DB.First(&vehicle, id)
	if result.RowsAffected == 0 {
		return dao.Vehicle{}, errors.New("车辆不存在")
	}
	return vehicle, nil
}

// GetVehicleByPlateNumber 根据车牌号或RFID获取车辆信息
func (s *VehicleService) GetVehicleByPlateNumber(plateNumber, RFIDTag string) (dao.Vehicle, error) {
	var vehicle dao.Vehicle
	query := global.GVA_DB.Preload("VehicleType")
	if RFIDTag != "" {
		query = query.Where("plate_number = ? OR rfid_tag = ?", plateNumber, RFIDTag)
	} else {
		query = query.Where("plate_number = ?", plateNumber)
	}
	result := query.First(&vehicle)
	if result.RowsAffected == 0 {
		return dao.Vehicle{}, errors.New("车辆不存在")
	}
	return vehicle, nil
}

func (s *VehicleService) QueryAllVehicles() ([]dao.Vehicle, error) {
	var vehicles []dao.Vehicle
	err := global.GVA_DB.Find(&vehicles).Error
	if err != nil {
		return vehicles, err
	}
	return vehicles, nil
}

// ListVehicles 获取车辆列表
func (s *VehicleService) ListVehicles(req request.VehicleQuery) (int64, []dao.Vehicle, error) {
	var vehicles []dao.Vehicle
	var total int64

	query := global.GVA_DB.Model(&dao.Vehicle{})

	if req.PlateNumber != "" {
		query = query.Where("plate_number LIKE ?", "%"+req.PlateNumber+"%")
	}

	if req.VehicleTypeID > 0 {
		query = query.Where("vehicle_type_id = ?", req.VehicleTypeID)
	}

	if req.OwnerId > 0 {
		query = query.Where("owner_id = ?", req.OwnerId)
	}

	// 计算总数
	query.Count(&total)

	// 分页查询
	offset := (req.Page - 1) * req.PageSize
	result := query.Offset(offset).Limit(req.PageSize).Preload("Owner").Preload("VehicleType").Find(&vehicles)
	if result.Error != nil {
		return 0, nil, result.Error
	}

	return total, vehicles, nil
}

// DeleteVehicle 删除车辆
func (s *VehicleService) DeleteVehicle(id uint) error {
	result := global.GVA_DB.Delete(&dao.Vehicle{}, id)
	if result.RowsAffected == 0 {
		return errors.New("车辆不存在")
	}
	return result.Error
}

// VehicleEntry 车辆入场
func (s *VehicleService) VehicleEntry(req request.VehicleEntry) (request.VehicleEntryResponse, error) {
	// 黑名单检查
	var shortlistSvc ShortlistService
	if isBlack, _ := shortlistSvc.CheckVehicleShortlist(req.PlateNumber, req.RFIDTag); isBlack {
		return request.VehicleEntryResponse{}, errors.New("车辆在黑名单中，禁止入场")
	}
	// 检查车辆是否存在
	vehicle, err := s.GetVehicleByPlateNumber(req.PlateNumber, req.RFIDTag)
	if err != nil {
		// 如果车辆不存在，创建新车辆，自动归类为"临时车"
		var tempType dao.VehicleType
		if global.GVA_DB.Where("is_system = ?", true).First(&tempType).Error != nil {
			return request.VehicleEntryResponse{}, errors.New("系统错误：临时车类型未配置")
		}
		createReq := request.VehicleCreate{
			PlateNumber:   req.PlateNumber,
			VehicleTypeID: tempType.ID,
			OwnerId:       0,
		}
		err = s.CreateVehicle(createReq)
		if err != nil {
			return request.VehicleEntryResponse{}, err
		}
		vehicle, _ = s.GetVehicleByPlateNumber(req.PlateNumber, req.RFIDTag)
	}

	// 检查是否有未出场的记录
	var existingRecord dao.VehicleRecord
	result := buildPlateOrRfidQuery(global.GVA_DB, req.PlateNumber, req.RFIDTag).Where("exit_time IS NULL").First(&existingRecord)
	if result.RowsAffected > 0 {
		return request.VehicleEntryResponse{}, errors.New("车辆已入场，未出场")
	}

	// 创建入场记录
	entryTime := time.Now()
	record := dao.VehicleRecord{
		PlateNumber:    req.PlateNumber,
		RFIDTag:        req.RFIDTag,
		EntryTime:      entryTime,
		ParkingLotID:   req.ParkingLotID,
		ParkingSpaceID: req.ParkingSpaceID,
		EntryImage:     req.EntryImage,
		PaymentStatus:  "unpaid",
	}

	err = global.GVA_DB.Create(&record).Error
	if err != nil {
		return request.VehicleEntryResponse{}, err
	}

	// 创建数字票（统一入口）
	ticketSvc := ticketService.NewTicketService()
	triggerMode := "manual"
	if req.RFIDTag != "" { triggerMode = "rfid" }
	ticketSvc.Create(req.PlateNumber, triggerMode, record.ID)
	// 更新车辆最近入场时间
	vehicle.LastEntryTime = &entryTime
	global.GVA_DB.Save(&vehicle)

	response := request.VehicleEntryResponse{
		Success: true,
		Message: "车辆入场成功",
	}
	response.Data.PlateNumber = req.PlateNumber
	response.Data.EntryTime = entryTime.Unix()
	response.Data.ParkingLotID = req.ParkingLotID
	response.Data.ParkingSpaceID = req.ParkingSpaceID

	return response, nil
}

// VehicleExit 车辆出场
func (s *VehicleService) VehicleExit(req request.VehicleExit) (request.VehicleExitResponse, error) {
	// 1. 查询未出场记录
	var record dao.VehicleRecord
	if err := buildPlateOrRfidQuery(global.GVA_DB, req.PlateNumber, req.RFIDTag).Where("exit_time IS NULL").First(&record).Error; err != nil {
		return request.VehicleExitResponse{}, errors.New("车辆未入场或已出场")
	}

	// 2. 获取车辆信息
	vehicle, err := s.GetVehicleByPlateNumber(req.PlateNumber, req.RFIDTag)
	if err != nil {
		return request.VehicleExitResponse{}, err
	}

	// 3. 计算停留时长 & 费用
	exitTime := time.Now()
	stayTime := int64(exitTime.Sub(record.EntryTime).Minutes())
	if stayTime < 0 {
		stayTime = 0
	}
	fee := s.calculateFee(&vehicle, stayTime)

	// 4. 更新出场记录
	record.ExitTime = &exitTime
	record.StayTime = stayTime
	record.Fee = fee
	record.ExitImage = req.ExitImage
	record.PaymentStatus = "paid"

	if err := global.GVA_DB.Save(&record).Error; err != nil {
		return request.VehicleExitResponse{}, err
	}

	// 5. 更新车辆统计信息
	vehicle.LastExitTime = &exitTime
	vehicle.TotalStayTime += stayTime
	vehicle.TotalFee += fee
	global.GVA_DB.Save(&vehicle)

	// 6. 完全匹配你的匿名结构体返回（正确写法）
	var response request.VehicleExitResponse
	response.Success = true
	response.Message = "车辆出场成功"
	response.Data.PlateNumber = record.PlateNumber
	response.Data.EntryTime = record.EntryTime.Unix()
	response.Data.ExitTime = exitTime.Unix()
	response.Data.StayTime = stayTime
	response.Data.Fee = fee
	response.Data.PaymentStatus = record.PaymentStatus

	return response, nil
}

// ExitPreview 费用预览（不修改数据库，仅查询+计算费用）
func (s *VehicleService) ExitPreview(req request.VehicleEntry) (vehicleResponse.ExitPreviewResponse, error) {
	var record dao.VehicleRecord
	err := buildPlateOrRfidQuery(global.GVA_DB, req.PlateNumber, req.RFIDTag).Where("exit_time IS NULL").First(&record).Error
	if err != nil {
		return vehicleResponse.ExitPreviewResponse{}, errors.New("车辆未入场或已出场")
	}

	vehicle, err := s.GetVehicleByPlateNumber(req.PlateNumber, req.RFIDTag)
	if err != nil {
		return vehicleResponse.ExitPreviewResponse{}, err
	}

	now := time.Now()
	stayTime := int64(now.Sub(record.EntryTime).Minutes())
	if stayTime < 0 {
		stayTime = 0
	}
	fee := s.calculateFee(&vehicle, stayTime)

	typeName := ""
	isTemp := false
	if vehicle.VehicleType != nil {
		typeName = vehicle.VehicleType.Name
		isTemp = vehicle.VehicleType.IsSystem
	}

	return vehicleResponse.ExitPreviewResponse{
		PlateNumber: vehicle.PlateNumber,
		EntryTime:   record.EntryTime.Unix(),
		StayTime:    stayTime,
		Fee:         fee,
		VehicleType: typeName,
		IsTemp:      isTemp,
	}, nil
}

// ExitConfirm 确认出场 + 支付（更新车辆记录 + 创建支付记录）
func (s *VehicleService) ExitConfirm(req request.ExitConfirmRequest, operatorID uint) (vehicleResponse.ExitConfirmResponse, error) {
	// 黑名单检查
	var shortlistSvc ShortlistService
	if isBlack, _ := shortlistSvc.CheckVehicleShortlist(req.PlateNumber, req.RFIDTag); isBlack {
		return vehicleResponse.ExitConfirmResponse{}, errors.New("车辆在黑名单中，禁止出场")
	}
	var record dao.VehicleRecord
	err := buildPlateOrRfidQuery(global.GVA_DB, req.PlateNumber, req.RFIDTag).Where("exit_time IS NULL").First(&record).Error
	if err != nil {
		return vehicleResponse.ExitConfirmResponse{}, errors.New("车辆未入场或已出场")
	}
	vehicle, err := s.GetVehicleByPlateNumber(req.PlateNumber, req.RFIDTag)
	if err != nil {
		return vehicleResponse.ExitConfirmResponse{}, err
	}
	exitTime := time.Now()
	stayTime := int64(exitTime.Sub(record.EntryTime).Minutes())
	if stayTime < 0 {
		stayTime = 0
	}
	fee := s.calculateFee(&vehicle, stayTime)
	record.ExitTime = &exitTime
	record.StayTime = stayTime
	record.Fee = fee
	record.PaymentMethod = req.PaymentMethod
	global.GVA_DB.Save(&record)
	vehicle.LastExitTime = &exitTime
	vehicle.TotalStayTime += stayTime
	vehicle.TotalFee += fee
	global.GVA_DB.Save(&vehicle)
	paymentSvc := paymentService.NewPaymentService()
	pr, err := paymentSvc.ProcessPayment(record.ID, req.PaymentMethod, fee, req.PaidAmount, operatorID)
	if err != nil {
		return vehicleResponse.ExitConfirmResponse{}, err
	}
	changeAmount := 0.0
	if pr != nil {
		changeAmount = pr.ChangeAmount
	}
	return vehicleResponse.ExitConfirmResponse{
		PlateNumber:   vehicle.PlateNumber,
		EntryTime:     record.EntryTime.Unix(),
		ExitTime:      exitTime.Unix(),
		StayTime:      stayTime,
		Fee:           fee,
		ChangeAmount:  changeAmount,
		PaymentMethod: req.PaymentMethod,
	}, nil
}

// calculateFee 计算停车费用
func (s *VehicleService) calculateFee(vehicle *dao.Vehicle, stayTime int64) float64 {
	// 1. 根据车辆类型ID获取收费配置（唯一）
	var feeConfig dao.FeeConfig
	if err := global.GVA_DB.Where("vehicle_type_id = ?", vehicle.VehicleTypeID).First(&feeConfig).Error; err != nil {
		// 无配置 → 默认计费：0.1元/分钟
		return float64(stayTime) * 0.1
	}
	// 配置存在但全为 0 → 同样回退默认费率
	if feeConfig.UnitFee == 0 && feeConfig.StartFee == 0 && feeConfig.DailyMaxFee == 0 {
		return float64(stayTime) * 0.1
	}

	// 2. 判断VIP有效性（必须IsVip=true、过期时间未到、且过期时间非零值）
	isVIP := false
	if vehicle.OwnerId != nil {
		var owner dao.Owner
		if err := global.GVA_DB.First(&owner, *vehicle.OwnerId).Error; err == nil {
			now := time.Now()
			isVIP = owner.IsVip && owner.VipExpireTime.After(now) && !owner.VipExpireTime.IsZero()
		}
	}

	// 3. VIP 免费
	if isVIP && feeConfig.IsVIPFree {
		return 0
	}

	// ===================== 修复这里 =====================
	// 4. 在免费时长内 → 直接 0 元
	if stayTime <= int64(feeConfig.StartTime) {
		return 0
	}

	// 5. 超过免费时长 → 开始计费
	extraTime := stayTime - int64(feeConfig.StartTime)
	extraUnits := extraTime / int64(feeConfig.UnitTime)
	if extraTime%int64(feeConfig.UnitTime) > 0 {
		extraUnits++
	}

	// 起步费 + 超时费用
	fee := feeConfig.StartFee + float64(extraUnits)*feeConfig.UnitFee

	// 6. 每日封顶
	if feeConfig.DailyMaxFee > 0 && fee > feeConfig.DailyMaxFee {
		fee = feeConfig.DailyMaxFee
	}

	// 7. VIP 折扣
	if isVIP {
		fee *= feeConfig.VIPDiscount
	}

	return fee
}

// InParkVehicle 在场车辆信息
type InParkVehicle struct {
	RecordID      uint    `json:"record_id"`
	PlateNumber   string  `json:"plate_number"`
	VehicleType   string  `json:"vehicle_type"`
	OwnerName     string  `json:"owner_name"`
	OwnerPhone    string  `json:"owner_phone"`
	EntryTime     string  `json:"entry_time"`
	StayMinutes   int64   `json:"stay_minutes"`
	ParkingLot    string  `json:"parking_lot"`
	ParkingSpace  string  `json:"parking_space"`
}

// GetInParkVehicles 获取所有在场车辆
func (s *VehicleService) GetInParkVehicles(lotID uint, plateNumber string) ([]InParkVehicle, error) {
	var results []InParkVehicle
	now := time.Now()
	query := global.GVA_DB.Table("vehicle_record").
		Select(`vehicle_record.id as record_id, vehicle_record.plate_number, vehicle_type.name as vehicle_type,
			owner.owner_name, owner.owner_phone, vehicle_record.entry_time,
			parking_lot.lot_name as parking_lot`).
		Joins("LEFT JOIN vehicle ON vehicle.plate_number = vehicle_record.plate_number").
		Joins("LEFT JOIN vehicle_type ON vehicle_type.id = vehicle.vehicle_type_id").
		Joins("LEFT JOIN owner ON owner.id = vehicle.owner_id").
		Joins("LEFT JOIN parking_lot ON parking_lot.id = vehicle_record.parking_lot_id").
		Where("vehicle_record.exit_time IS NULL")
	if lotID > 0 {
		query = query.Where("vehicle_record.parking_lot_id = ?", lotID)
	}
	if plateNumber != "" {
		query = query.Where("vehicle_record.plate_number LIKE ?", "%"+plateNumber+"%")
	}
	err := query.Order("vehicle_record.entry_time ASC").Scan(&results).Error
	if err != nil {
		return nil, err
	}
	for i := range results {
		// Parse entry time and calculate stay duration
		t, parseErr := time.Parse("2006-01-02T15:04:05-07:00", results[i].EntryTime)
		if parseErr != nil {
			t, _ = time.Parse("2006-01-02 15:04:05", results[i].EntryTime)
		}
		results[i].StayMinutes = int64(now.Sub(t).Minutes())
		if results[i].StayMinutes < 0 {
			results[i].StayMinutes = 0
		}
	}
	return results, nil
}
