package de.votian.services.controller;

import de.votian.services.dto.AcceptanceProtocolDto;
import de.votian.services.dto.CustomerAcceptanceProtocolConfigDto;
import de.votian.services.dto.CustomerDeliveryReasonConfigDto;
import de.votian.services.dto.CustomerServiceConfigDto;
import de.votian.services.dto.DeliveryReasonListDto;
import de.votian.services.dto.ServiceRadiusDto;
import de.votian.services.dto.ServiceZoneDto;
import de.votian.services.dto.ServiceZoneMappingDto;
import de.votian.services.dto.UserSessionDto;
import de.votian.services.security.AccessControlService;
import de.votian.services.service.CustomerServiceConfigService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.List;

@RestController
@RequestMapping("/api/customers")
public class CustomerServiceConfigController {

    private final CustomerServiceConfigService customerServiceConfigService;
    private final AccessControlService accessControlService;

    public CustomerServiceConfigController(CustomerServiceConfigService customerServiceConfigService,
                                           AccessControlService accessControlService) {
        this.customerServiceConfigService = customerServiceConfigService;
        this.accessControlService = accessControlService;
    }

    @GetMapping("/{id}/service-config")
    public ResponseEntity<CustomerServiceConfigDto> getConfiguration(@PathVariable Long id, Authentication authentication) {
        if (!canViewCustomer(authentication, id)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(customerServiceConfigService.getConfiguration(id));
    }

    @PutMapping("/{id}/service-config")
    public ResponseEntity<Void> saveConfiguration(@PathVariable Long id,
                                                  @RequestBody ServiceConfigRequest request,
                                                  Authentication authentication) {
        if (!canManageCustomer(authentication, id)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        customerServiceConfigService.saveConfiguration(id, request.serviceIds, request.serviceTypeIds);
        return ResponseEntity.ok().build();
    }

    @GetMapping("/{id}/delivery-reasons")
    public ResponseEntity<CustomerDeliveryReasonConfigDto> getDeliveryReasons(@PathVariable Long id,
                                                                              Authentication authentication) {
        if (!canViewCustomer(authentication, id)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(customerServiceConfigService.getDeliveryReasons(id));
    }

    @PutMapping("/{id}/delivery-reasons")
    public ResponseEntity<Void> saveDeliveryReasons(@PathVariable Long id,
                                                    @RequestBody DeliveryReasonConfigRequest request,
                                                    Authentication authentication) {
        if (!canManageCustomer(authentication, id)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        customerServiceConfigService.saveDeliveryReasons(id, request != null ? request.lists : List.of());
        return ResponseEntity.ok().build();
    }

    @GetMapping("/{id}/acceptance-protocols")
    public ResponseEntity<CustomerAcceptanceProtocolConfigDto> getAcceptanceProtocols(@PathVariable Long id,
                                                                                      Authentication authentication) {
        if (!canViewCustomer(authentication, id)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(customerServiceConfigService.getAcceptanceProtocols(id));
    }

    @PutMapping("/{id}/acceptance-protocols")
    public ResponseEntity<Void> saveAcceptanceProtocols(@PathVariable Long id,
                                                        @RequestBody AcceptanceProtocolConfigRequest request,
                                                        Authentication authentication) {
        if (!canManageCustomer(authentication, id)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        customerServiceConfigService.saveAcceptanceProtocols(id, request != null ? request.protocols : List.of());
        return ResponseEntity.ok().build();
    }

    @GetMapping("/{id}/service-zones")
    public ResponseEntity<List<ServiceZoneDto>> getZones(@PathVariable Long id, Authentication authentication) {
        if (!canViewCustomer(authentication, id)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(customerServiceConfigService.getZones(id));
    }

    @PostMapping("/{id}/service-zones")
    public ResponseEntity<ServiceZoneDto> createZone(@PathVariable Long id,
                                                     @RequestBody ServiceZoneRequest request,
                                                     Authentication authentication) {
        if (!canManageCustomer(authentication, id)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(customerServiceConfigService.createZone(
                id, request.name, request.price, request.price1, request.price2, request.price3));
    }

    @PutMapping("/{id}/service-zones/{zoneId}")
    public ResponseEntity<ServiceZoneDto> updateZone(@PathVariable Long id,
                                                     @PathVariable Long zoneId,
                                                     @RequestBody ServiceZoneRequest request,
                                                     Authentication authentication) {
        if (!canManageCustomer(authentication, id)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(customerServiceConfigService.updateZone(
                id, zoneId, request.name, request.price, request.price1, request.price2, request.price3));
    }

    @DeleteMapping("/{id}/service-zones/{zoneId}")
    public ResponseEntity<Void> deleteZone(@PathVariable Long id,
                                           @PathVariable Long zoneId,
                                           Authentication authentication) {
        if (!canManageCustomer(authentication, id)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        customerServiceConfigService.deleteZone(id, zoneId);
        return ResponseEntity.ok().build();
    }

    @GetMapping("/{id}/service-zone-mappings")
    public ResponseEntity<List<ServiceZoneMappingDto>> getZoneMappings(@PathVariable Long id,
                                                                       Authentication authentication) {
        if (!canViewCustomer(authentication, id)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(customerServiceConfigService.getZoneMappings(id));
    }

    @PostMapping("/{id}/service-zone-mappings")
    public ResponseEntity<ServiceZoneMappingDto> createZoneMapping(@PathVariable Long id,
                                                                   @RequestBody ServiceZoneMappingRequest request,
                                                                   Authentication authentication) {
        if (!canManageCustomer(authentication, id)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(customerServiceConfigService.createZoneMapping(
                id, request.zoneId, request.zipcode, request.mappedValue1, request.mappedValue2, request.mappedValue3));
    }

    @PutMapping("/{id}/service-zone-mappings/{zoneId}/{zipCodeId}")
    public ResponseEntity<ServiceZoneMappingDto> updateZoneMapping(@PathVariable Long id,
                                                                   @PathVariable Long zoneId,
                                                                   @PathVariable Long zipCodeId,
                                                                   @RequestBody ServiceZoneMappingRequest request,
                                                                   Authentication authentication) {
        if (!canManageCustomer(authentication, id)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(customerServiceConfigService.updateZoneMapping(
                id, zoneId, zipCodeId, request.zoneId, request.zipcode, request.mappedValue1, request.mappedValue2, request.mappedValue3));
    }

    @DeleteMapping("/{id}/service-zone-mappings/{zoneId}/{zipCodeId}")
    public ResponseEntity<Void> deleteZoneMapping(@PathVariable Long id,
                                                  @PathVariable Long zoneId,
                                                  @PathVariable Long zipCodeId,
                                                  Authentication authentication) {
        if (!canManageCustomer(authentication, id)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        customerServiceConfigService.deleteZoneMapping(id, zoneId, zipCodeId);
        return ResponseEntity.ok().build();
    }

    @GetMapping("/{id}/service-radii")
    public ResponseEntity<List<ServiceRadiusDto>> getRadii(@PathVariable Long id, Authentication authentication) {
        if (!canViewCustomer(authentication, id)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(customerServiceConfigService.getRadii(id));
    }

    @PostMapping("/{id}/service-radii")
    public ResponseEntity<ServiceRadiusDto> createRadius(@PathVariable Long id,
                                                         @RequestBody ServiceRadiusRequest request,
                                                         Authentication authentication) {
        if (!canManageCustomer(authentication, id)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(customerServiceConfigService.createRadius(
                id, request.zipcode, request.cityDistrict, request.radiusAreaNo));
    }

    @PutMapping("/{id}/service-radii/{radiusId}")
    public ResponseEntity<ServiceRadiusDto> updateRadius(@PathVariable Long id,
                                                         @PathVariable Long radiusId,
                                                         @RequestBody ServiceRadiusRequest request,
                                                         Authentication authentication) {
        if (!canManageCustomer(authentication, id)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(customerServiceConfigService.updateRadius(
                id, radiusId, request.zipcode, request.cityDistrict, request.radiusAreaNo));
    }

    @DeleteMapping("/{id}/service-radii/{radiusId}")
    public ResponseEntity<Void> deleteRadius(@PathVariable Long id,
                                             @PathVariable Long radiusId,
                                             Authentication authentication) {
        if (!canManageCustomer(authentication, id)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        customerServiceConfigService.deleteRadius(id, radiusId);
        return ResponseEntity.ok().build();
    }

    private boolean canViewCustomer(Authentication authentication, Long customerId) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        return accessControlService.canAccessCustomer(user, customerId);
    }

    private boolean canManageCustomer(Authentication authentication, Long customerId) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        return accessControlService.canManageCustomers(user) && accessControlService.canAccessCustomer(user, customerId);
    }

    public static class ServiceConfigRequest {
        public List<Long> serviceIds;
        public List<Long> serviceTypeIds;
    }

    public static class ServiceZoneRequest {
        public String name;
        public BigDecimal price;
        public BigDecimal price1;
        public BigDecimal price2;
        public BigDecimal price3;
    }

    public static class ServiceZoneMappingRequest {
        public Long zoneId;
        public String zipcode;
        public BigDecimal mappedValue1;
        public BigDecimal mappedValue2;
        public BigDecimal mappedValue3;
    }

    public static class ServiceRadiusRequest {
        public String zipcode;
        public String cityDistrict;
        public Integer radiusAreaNo;
    }

    public static class DeliveryReasonConfigRequest {
        public List<DeliveryReasonListDto> lists;
    }

    public static class AcceptanceProtocolConfigRequest {
        public List<AcceptanceProtocolDto> protocols;
    }
}
