package com.mvrent.carrental.controller;

import com.mvrent.carrental.model.*;
import com.mvrent.carrental.service.DriverService;
import com.mvrent.carrental.service.FileStorageService;
import com.mvrent.carrental.web.DriverDto;
import com.mvrent.carrental.web.DriverForm;
import com.mvrent.carrental.web.DriverMediaDto;
import lombok.RequiredArgsConstructor;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDate;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/** JSON API backing the AJAX Manage Drivers screen. */
@RestController
@RequestMapping("/admin/api/drivers")
@RequiredArgsConstructor
@PreAuthorize("hasRole('ADMIN') or hasAuthority('MANAGE_DRIVERS')")
public class AdminDriverApiController {

    private final DriverService driverService;
    private final FileStorageService fileStorage;

    @GetMapping
    public List<DriverDto> list() {
        return driverService.findAll().stream().map(DriverDto::from).toList();
    }

    @GetMapping("/{id}")
    public DriverDto get(@PathVariable Long id) {
        return DriverDto.from(driverService.findById(id));
    }

    @PostMapping
    public ResponseEntity<?> save(@RequestBody DriverForm f) {
        Map<String, String> errors = new LinkedHashMap<>();
        if (isBlank(f.name())) errors.put("name", "Name is required");
        if (isBlank(f.licenceNumber())) errors.put("licenceNumber", "Licence number is required");
        if (!errors.isEmpty()) {
            return ResponseEntity.badRequest().body(Map.of("ok", false, "errors", errors));
        }

        Driver d = new Driver();
        if (f.id() != null) d.setId(f.id());
        d.setName(trim(f.name()));
        d.setPhone(trim(f.phone()));
        d.setLicenceNumber(trim(f.licenceNumber()));
        d.setLicenceExpiry(f.licenceExpiry());
        d.setYearsExperience(f.yearsExperience() == null ? 0 : f.yearsExperience());
        d.setEmploymentType(f.employmentType() == null ? DriverEmploymentType.EMPLOYED : f.employmentType());
        d.setHourlyCharge(f.hourlyCharge());
        d.setDailyCharge(f.dailyCharge());
        d.setMonthlyCharge(f.monthlyCharge());
        d.setStatus(f.status() == null ? DriverStatus.AVAILABLE : f.status());
        d.setPhotoUrl(trim(f.photoUrl()));

        try {
            Driver saved = driverService.saveFromForm(d, f.categoryId(), f.vendorId());
            return ResponseEntity.ok(Map.of("ok", true, "driver", DriverDto.from(saved)));
        } catch (DataIntegrityViolationException ex) {
            return ResponseEntity.badRequest().body(Map.of("ok", false,
                    "errors", Map.of("licenceNumber", "Licence number already exists")));
        }
    }

    /* ---------- Documents ---------- */

    @GetMapping("/{id}/documents")
    public DriverMediaDto documents(@PathVariable Long id) {
        return DriverMediaDto.from(driverService.findById(id));
    }

    @PostMapping("/{id}/documents")
    public ResponseEntity<?> addDocument(@PathVariable Long id,
                                         @RequestParam DriverDocumentType docType,
                                         @RequestParam(required = false) MultipartFile file,
                                         @RequestParam(required = false) String fileUrl,
                                         @RequestParam(required = false)
                                         @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate issuedDate,
                                         @RequestParam(required = false)
                                         @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate expiryDate) {
        String stored = fileStorage.store(file);
        String url = stored != null ? stored : fileUrl;
        if (url == null || url.isBlank()) {
            return ResponseEntity.badRequest().body(Map.of("ok", false, "message", "Upload a file or provide a URL"));
        }
        driverService.addDocument(id, docType, url, issuedDate, expiryDate);
        return ResponseEntity.ok(Map.of("ok", true));
    }

    @PostMapping("/{id}/documents/{docId}/delete")
    public ResponseEntity<?> deleteDocument(@PathVariable Long id, @PathVariable Long docId) {
        driverService.deleteDocument(docId);
        return ResponseEntity.ok(Map.of("ok", true));
    }

    @PostMapping("/{id}/delete")
    public ResponseEntity<?> delete(@PathVariable Long id) {
        try {
            driverService.delete(id);
            return ResponseEntity.ok(Map.of("ok", true));
        } catch (DataIntegrityViolationException ex) {
            return ResponseEntity.badRequest().body(Map.of("ok", false,
                    "message", "Cannot delete — this driver has trips. Set status to OFF instead."));
        }
    }

    /** Inline activate/deactivate: flips a driver between AVAILABLE and OFF. */
    @PostMapping("/{id}/status")
    public ResponseEntity<?> setStatus(@PathVariable Long id, @RequestParam DriverStatus status) {
        Driver saved = driverService.updateStatus(id, status);
        return ResponseEntity.ok(Map.of("ok", true, "id", id, "status", saved.getStatus().name()));
    }

    private static boolean isBlank(String s) { return s == null || s.isBlank(); }
    private static String trim(String s) { return s == null ? null : s.trim(); }
}
