package de.votian.services.controller;

import de.votian.services.dto.CourierDetailDto;
import de.votian.services.dto.CourierListItemDto;
import de.votian.services.dto.UserSessionDto;
import de.votian.services.entity.Address;
import de.votian.services.entity.Courier;
import de.votian.services.entity.CourierVehicle;
import de.votian.services.security.AccessControlService;
import de.votian.services.service.CourierService;
import de.votian.services.service.ViewDataService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/couriers")
public class CourierController {

    private final CourierService courierService;
    private final ViewDataService viewDataService;
    private final AccessControlService accessControlService;

    public CourierController(CourierService courierService,
                             ViewDataService viewDataService,
                             AccessControlService accessControlService) {
        this.courierService = courierService;
        this.viewDataService = viewDataService;
        this.accessControlService = accessControlService;
    }

    @GetMapping("/{id}")
    public ResponseEntity<CourierDetailDto> findById(@PathVariable Long id, Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!accessControlService.canViewCouriers(user)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return viewDataService.findCourierDetail(id)
                .map(courier -> accessControlService.canAccessHeadquarters(user, courier.getHeadquartersId())
                        ? ResponseEntity.ok(courier)
                        : ResponseEntity.status(HttpStatus.FORBIDDEN).<CourierDetailDto>build())
                .orElse(ResponseEntity.notFound().build());
    }

    @GetMapping("/hq/{hqId}")
    public ResponseEntity<List<CourierListItemDto>> findByHeadquarters(@PathVariable Long hqId,
                                                                       Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!accessControlService.canViewCouriers(user) || !accessControlService.canAccessHeadquarters(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(viewDataService.findCouriersByHeadquarters(hqId));
    }

    @GetMapping("/search")
    public ResponseEntity<List<CourierListItemDto>> search(@RequestParam Long hqId,
                                                           @RequestParam String term,
                                                           Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!accessControlService.canViewCouriers(user) || !accessControlService.canAccessHeadquarters(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(viewDataService.searchCouriers(hqId, term));
    }

    @GetMapping("/sid-unique")
    public ResponseEntity<Boolean> isSidUnique(@RequestParam String sid,
                                               @RequestParam Long hqId,
                                               Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!accessControlService.canManageCouriers(user) || !accessControlService.canAccessHeadquarters(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(courierService.isSidUnique(sid, hqId));
    }

    @GetMapping("/eid-unique")
    public ResponseEntity<Boolean> isEidUnique(@RequestParam String eid,
                                               @RequestParam Long hqId,
                                               Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!accessControlService.canManageCouriers(user) || !accessControlService.canAccessHeadquarters(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(courierService.isEidUnique(eid, hqId));
    }

    @PostMapping
    public ResponseEntity<Courier> create(@RequestBody CourierCreateRequest request, Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (request == null
                || request.courier == null
                || !accessControlService.canManageCouriers(user)
                || !accessControlService.canAccessHeadquarters(user, request.courier.getHeadquartersId())) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        Courier courier = courierService.createCourier(
                request.courier, request.company, request.user, request.address, request.password);
        return ResponseEntity.ok(courier);
    }

    @PutMapping("/{id}")
    public ResponseEntity<Courier> update(@PathVariable Long id,
                                          @RequestBody CourierUpdateRequest request,
                                          Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        Courier existing = courierService.findById(id).orElse(null);
        if (existing == null) {
            return ResponseEntity.notFound().build();
        }
        if (!accessControlService.canManageCouriers(user)
                || !accessControlService.canAccessHeadquarters(user, existing.getHeadquartersId())) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        Courier updated = courierService.updateCourier(id, request.courier, request.company, request.user, request.address);
        return ResponseEntity.ok(updated);
    }

    @GetMapping("/{id}/vehicles")
    public ResponseEntity<List<CourierVehicle>> getVehicles(@PathVariable Long id, Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        Courier existing = courierService.findById(id).orElse(null);
        if (existing == null) {
            return ResponseEntity.notFound().build();
        }
        if (!accessControlService.canViewCouriers(user)
                || !accessControlService.canAccessHeadquarters(user, existing.getHeadquartersId())) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(courierService.getVehicles(id));
    }

    @PostMapping("/{id}/vehicles")
    public ResponseEntity<CourierVehicle> addVehicle(@PathVariable Long id,
                                                     @RequestBody CourierVehicle vehicle,
                                                     Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        Courier existing = courierService.findById(id).orElse(null);
        if (existing == null) {
            return ResponseEntity.notFound().build();
        }
        if (!accessControlService.canManageCouriers(user)
                || !accessControlService.canAccessHeadquarters(user, existing.getHeadquartersId())) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        vehicle.setCourierId(id);
        return ResponseEntity.ok(courierService.saveVehicle(vehicle));
    }

    @PutMapping("/{id}/vehicles/{vehicleId}")
    public ResponseEntity<CourierVehicle> updateVehicle(@PathVariable Long id,
                                                        @PathVariable Long vehicleId,
                                                        @RequestBody CourierVehicle vehicle,
                                                        Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        Courier existing = courierService.findById(id).orElse(null);
        if (existing == null) {
            return ResponseEntity.notFound().build();
        }
        if (!accessControlService.canManageCouriers(user)
                || !accessControlService.canAccessHeadquarters(user, existing.getHeadquartersId())) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(courierService.updateVehicle(id, vehicleId, vehicle));
    }

    @DeleteMapping("/{id}/vehicles/{vehicleId}")
    public ResponseEntity<Void> deleteVehicle(@PathVariable Long id,
                                              @PathVariable Long vehicleId,
                                              Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        Courier existing = courierService.findById(id).orElse(null);
        if (existing == null) {
            return ResponseEntity.notFound().build();
        }
        if (!accessControlService.canManageCouriers(user)
                || !accessControlService.canAccessHeadquarters(user, existing.getHeadquartersId())) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        courierService.deleteVehicle(id, vehicleId);
        return ResponseEntity.ok().build();
    }

    public static class CourierCreateRequest {
        public Courier courier;
        public de.votian.services.entity.Company company;
        public Address address;
        public de.votian.services.entity.User user;
        public String password;
    }

    public static class CourierUpdateRequest {
        public Courier courier;
        public de.votian.services.entity.Company company;
        public Address address;
        public de.votian.services.entity.User user;
    }
}
