package com.mvrent.carrental.controller;

import com.mvrent.carrental.model.User;
import com.mvrent.carrental.model.Vendor;
import com.mvrent.carrental.model.VendorSettlement;
import com.mvrent.carrental.service.ConfigService;
import com.mvrent.carrental.service.ExcelService;
import com.mvrent.carrental.service.PdfService;
import com.mvrent.carrental.service.SettlementService;
import com.mvrent.carrental.service.UserService;
import com.mvrent.carrental.service.VendorService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import java.util.Map;

/** Self-service portal scoped to the logged-in vendor's own data. */
@Controller
@RequestMapping("/vendor")
@RequiredArgsConstructor
public class VendorPortalController {

    private final UserService userService;
    private final VendorService vendorService;
    private final SettlementService settlementService;
    private final PdfService pdfService;
    private final ExcelService excelService;
    private final ConfigService configService;

    private Vendor currentVendor(UserDetails principal) {
        User user = userService.findByUsername(principal.getUsername());
        Vendor vendor = user.getVendor();
        if (vendor == null) {
            throw new ResponseStatusException(HttpStatus.FORBIDDEN, "No vendor linked to this account");
        }
        return vendor;
    }

    @GetMapping
    public String dashboard(@AuthenticationPrincipal UserDetails principal, Model model) {
        Vendor vendor = currentVendor(principal);
        model.addAttribute("vendor", vendor);
        model.addAttribute("carCount", vendorService.cars(vendor.getId()).size());
        model.addAttribute("driverCount", vendorService.drivers(vendor.getId()).size());
        model.addAttribute("revenue", vendorService.revenue(vendor.getId()));
        model.addAttribute("recentTrips", vendorService.trips(vendor.getId()).stream().limit(5).toList());
        return "vendor/dashboard";
    }

    @GetMapping("/cars")
    public String cars(@AuthenticationPrincipal UserDetails principal, Model model) {
        Vendor vendor = currentVendor(principal);
        model.addAttribute("vendor", vendor);
        model.addAttribute("cars", vendorService.cars(vendor.getId()));
        return "vendor/cars";
    }

    @GetMapping("/drivers")
    public String drivers(@AuthenticationPrincipal UserDetails principal, Model model) {
        Vendor vendor = currentVendor(principal);
        model.addAttribute("vendor", vendor);
        model.addAttribute("drivers", vendorService.drivers(vendor.getId()));
        return "vendor/drivers";
    }

    @GetMapping("/trips")
    public String trips(@AuthenticationPrincipal UserDetails principal, Model model) {
        Vendor vendor = currentVendor(principal);
        model.addAttribute("vendor", vendor);
        model.addAttribute("trips", vendorService.trips(vendor.getId()));
        model.addAttribute("revenue", vendorService.revenue(vendor.getId()));
        return "vendor/trips";
    }

    @GetMapping("/settlements")
    public String settlements(@AuthenticationPrincipal UserDetails principal, Model model) {
        Vendor vendor = currentVendor(principal);
        model.addAttribute("vendor", vendor);
        model.addAttribute("settlements", settlementService.findByVendor(vendor.getId()));
        return "vendor/settlements";
    }

    private VendorSettlement ownSettlement(UserDetails principal, Long id) {
        Vendor vendor = currentVendor(principal);
        VendorSettlement s = settlementService.findById(id);
        if (!s.getVendor().getId().equals(vendor.getId())) {
            throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Not your settlement");
        }
        return s;
    }

    @GetMapping("/settlements/{id}/pdf")
    public ResponseEntity<byte[]> settlementPdf(@AuthenticationPrincipal UserDetails principal,
                                                @PathVariable Long id) {
        VendorSettlement s = ownSettlement(principal, id);
        byte[] pdf = pdfService.render("pdf/settlement", Map.of(
                "settlement", s, "trips", settlementService.tripsFor(s),
                "orgName", configService.getOrganization().getName()));
        return ResponseEntity.ok().contentType(MediaType.APPLICATION_PDF)
                .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"settlement-" + s.getId() + ".pdf\"")
                .body(pdf);
    }

    @GetMapping("/settlements/{id}/excel")
    public ResponseEntity<byte[]> settlementExcel(@AuthenticationPrincipal UserDetails principal,
                                                  @PathVariable Long id) {
        VendorSettlement s = ownSettlement(principal, id);
        byte[] xlsx = excelService.settlementWorkbook(s, settlementService.tripsFor(s));
        return ResponseEntity.ok().contentType(AdminSettlementController.XLSX)
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"settlement-" + s.getId() + ".xlsx\"")
                .body(xlsx);
    }
}
