package platform

import (
	"context"
	"database/sql"
	"fmt"
	"strings"
)

func (s *ProductionStore) VehicleLocationSourceHistory(ctx context.Context, vin string) ([]vehicleLocationSourceHistory, error) {
	rows, err := s.db.QueryContext(ctx, `SELECT protocol, source_key,
COALESCE(DATE_FORMAT(MIN(first_event_time), '%Y-%m-%d %H:%i:%s'), ''),
COALESCE(DATE_FORMAT(MAX(latest_event_time), '%Y-%m-%d %H:%i:%s'), ''),
COALESCE(SUM(sample_count), 0)
FROM vehicle_daily_mileage_source
WHERE vin = ?
GROUP BY protocol, source_key
ORDER BY protocol, source_key`, vin)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	items := make([]vehicleLocationSourceHistory, 0, 8)
	for rows.Next() {
		var item vehicleLocationSourceHistory
		if err := rows.Scan(&item.Protocol, &item.sourceKey, &item.FirstSeenAt, &item.LastSeenAt, &item.ReportSampleCount); err != nil {
			return nil, err
		}
		items = append(items, item)
	}
	return items, rows.Err()
}

func (s *ProductionStore) VehicleSourcePolicy(ctx context.Context, vin string) (VehicleSourcePolicyConfig, error) {
	config := VehicleSourcePolicyConfig{VIN: vin, Version: 1, UpdatedBy: "system", Audit: []VehicleSourcePolicyAudit{}}
	var updatedAt sql.NullString
	err := s.db.QueryRowContext(ctx, `SELECT version, updated_by,
DATE_FORMAT(updated_at, '%Y-%m-%d %H:%i:%s')
FROM platform_vehicle_source_policy_version WHERE vin = ?`, vin).Scan(&config.Version, &config.UpdatedBy, &updatedAt)
	if err != nil && err != sql.ErrNoRows {
		return VehicleSourcePolicyConfig{}, err
	}
	if updatedAt.Valid {
		config.UpdatedAt = normalizeAccessTime(updatedAt.String)
	}
	rows, err := s.db.QueryContext(ctx, `SELECT version, protocol, source_ref, source_label, actor,
DATE_FORMAT(changed_at, '%Y-%m-%d %H:%i:%s'), summary
FROM platform_vehicle_source_policy_audit
WHERE vin = ?
ORDER BY changed_at DESC, id DESC
LIMIT 20`, vin)
	if err != nil {
		return VehicleSourcePolicyConfig{}, err
	}
	defer rows.Close()
	for rows.Next() {
		var item VehicleSourcePolicyAudit
		if err := rows.Scan(&item.Version, &item.Protocol, &item.SourceRef, &item.SourceLabel, &item.Actor, &item.ChangedAt, &item.Summary); err != nil {
			return VehicleSourcePolicyConfig{}, err
		}
		item.ChangedAt = normalizeAccessTime(item.ChangedAt)
		config.Audit = append(config.Audit, item)
	}
	return config, rows.Err()
}

func (s *ProductionStore) SaveVehicleSourcePolicy(ctx context.Context, update vehicleSourcePolicyStoreUpdate) (VehicleSourcePolicyConfig, error) {
	tx, err := s.db.BeginTx(ctx, &sql.TxOptions{})
	if err != nil {
		return VehicleSourcePolicyConfig{}, err
	}
	defer tx.Rollback()
	if _, err := tx.ExecContext(ctx, `INSERT IGNORE INTO platform_vehicle_source_policy_version
(vin, version, updated_by) VALUES (?, 1, 'system')`, update.VIN); err != nil {
		return VehicleSourcePolicyConfig{}, err
	}
	var currentVersion int
	if err := tx.QueryRowContext(ctx, `SELECT version FROM platform_vehicle_source_policy_version
WHERE vin = ? FOR UPDATE`, update.VIN).Scan(&currentVersion); err != nil {
		return VehicleSourcePolicyConfig{}, err
	}
	if currentVersion != update.Version {
		return VehicleSourcePolicyConfig{}, clientError{Code: "SOURCE_POLICY_VERSION_CONFLICT", Message: "来源策略已被其他用户更新，请刷新后重试"}
	}
	currentEnabled := update.CurrentEnabled
	currentPriority := update.CurrentPriority
	currentRemark := update.CurrentRemark
	var enabled int
	err = tx.QueryRowContext(ctx, `SELECT enabled, priority, remark
FROM vehicle_location_source_policy
WHERE vin = ? AND protocol = ? AND source_key = ?`,
		update.VIN, update.Protocol, update.SourceKey,
	).Scan(&enabled, &currentPriority, &currentRemark)
	if err == nil {
		currentEnabled = enabled == 1
	} else if err != sql.ErrNoRows {
		return VehicleSourcePolicyConfig{}, err
	}
	if currentEnabled == update.Enabled && currentPriority == update.Priority && strings.TrimSpace(currentRemark) == update.Remark {
		if err := tx.Rollback(); err != nil {
			return VehicleSourcePolicyConfig{}, err
		}
		return s.VehicleSourcePolicy(ctx, update.VIN)
	}
	if _, err := tx.ExecContext(ctx, `INSERT INTO vehicle_location_source_policy
(vin, protocol, source_key, enabled, priority, remark)
VALUES (?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE enabled = VALUES(enabled), priority = VALUES(priority),
remark = VALUES(remark), updated_at = CURRENT_TIMESTAMP`,
		update.VIN, update.Protocol, update.SourceKey, boolInt(update.Enabled), update.Priority, update.Remark,
	); err != nil {
		return VehicleSourcePolicyConfig{}, err
	}
	nextVersion := currentVersion + 1
	result, err := tx.ExecContext(ctx, `UPDATE platform_vehicle_source_policy_version
SET version = ?, updated_by = ?, updated_at = CURRENT_TIMESTAMP
WHERE vin = ? AND version = ?`, nextVersion, update.Actor, update.VIN, currentVersion)
	if err != nil {
		return VehicleSourcePolicyConfig{}, err
	}
	if affected, err := result.RowsAffected(); err != nil || affected != 1 {
		return VehicleSourcePolicyConfig{}, clientError{Code: "SOURCE_POLICY_VERSION_CONFLICT", Message: "来源策略更新冲突，请刷新后重试"}
	}
	summary := fmt.Sprintf(
		"%s：%s→%s，优先级 %d→%d",
		update.SourceLabel,
		enabledLabel(currentEnabled), enabledLabel(update.Enabled),
		currentPriority, update.Priority,
	)
	if update.Remark != "" {
		summary += "；" + update.Remark
	}
	if _, err := tx.ExecContext(ctx, `INSERT INTO platform_vehicle_source_policy_audit
(vin, version, protocol, source_ref, source_key, source_label,
old_enabled, new_enabled, old_priority, new_priority, old_remark, new_remark,
actor, summary)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
		update.VIN, nextVersion, update.Protocol, update.SourceRef, update.SourceKey, update.SourceLabel,
		boolInt(currentEnabled), boolInt(update.Enabled), currentPriority, update.Priority, currentRemark, update.Remark,
		update.Actor, summary,
	); err != nil {
		return VehicleSourcePolicyConfig{}, err
	}
	if err := tx.Commit(); err != nil {
		return VehicleSourcePolicyConfig{}, err
	}
	return s.VehicleSourcePolicy(ctx, update.VIN)
}

func boolInt(value bool) int {
	if value {
		return 1
	}
	return 0
}

func enabledLabel(value bool) string {
	if value {
		return "启用"
	}
	return "停用"
}
