package de.votian.services.controller;

import de.votian.services.dto.CustomerDetailDto;
import de.votian.services.dto.CustomerListItemDto;
import de.votian.services.dto.UserSessionDto;
import de.votian.services.entity.CostCenter;
import de.votian.services.entity.Customer;
import de.votian.services.security.AccessControlService;
import de.votian.services.service.CustomerService;
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/customers")
public class CustomerController {

    private final CustomerService customerService;
    private final ViewDataService viewDataService;
    private final AccessControlService accessControlService;

    public CustomerController(CustomerService customerService,
                              ViewDataService viewDataService,
                              AccessControlService accessControlService) {
        this.customerService = customerService;
        this.viewDataService = viewDataService;
        this.accessControlService = accessControlService;
    }

    @GetMapping("/{id}")
    public ResponseEntity<CustomerDetailDto> findById(@PathVariable Long id, Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        return viewDataService.findCustomerDetail(id)
                .map(customer -> accessControlService.canAccessCustomer(user, customer.getId())
                        ? ResponseEntity.ok(customer)
                        : ResponseEntity.status(HttpStatus.FORBIDDEN).<CustomerDetailDto>build())
                .orElse(ResponseEntity.notFound().build());
    }

    @GetMapping("/eid/{eid}")
    public ResponseEntity<Customer> findByEid(@PathVariable String eid, Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!accessControlService.canViewCustomers(user)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return customerService.findByEid(eid)
                .map(customer -> accessControlService.canAccessHeadquarters(user, customer.getHeadquartersId())
                        ? ResponseEntity.ok(customer)
                        : ResponseEntity.status(HttpStatus.FORBIDDEN).<Customer>build())
                .orElse(ResponseEntity.notFound().build());
    }

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

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

    @PostMapping
    public ResponseEntity<Customer> create(@RequestBody CustomerCreateRequest request, Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (request == null
                || request.customer == null
                || !accessControlService.canManageCustomers(user)
                || !accessControlService.canAccessHeadquarters(user, request.customer.getHeadquartersId())) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        Customer customer = customerService.createCustomer(
                request.customer, request.company, request.user, request.password);
        return ResponseEntity.ok(customer);
    }

    @PutMapping("/{id}")
    public ResponseEntity<Customer> update(@PathVariable Long id,
                                           @RequestBody CustomerUpdateRequest request,
                                           Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        Customer existing = customerService.findById(id).orElse(null);
        if (existing == null) {
            return ResponseEntity.notFound().build();
        }
        if (!accessControlService.canManageCustomers(user)
                || !accessControlService.canAccessHeadquarters(user, existing.getHeadquartersId())) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        Customer updated = customerService.updateCustomer(id, request.customer, request.company, request.user);
        return ResponseEntity.ok(updated);
    }

    @GetMapping("/{id}/costcenters")
    public ResponseEntity<List<CostCenter>> getCostCenters(@PathVariable Long id, Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!accessControlService.canAccessCustomer(user, id)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(customerService.getCostCenters(id));
    }

    @GetMapping("/{id}/costcenters/visible")
    public ResponseEntity<List<CostCenter>> getVisibleCostCenters(@PathVariable Long id, Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!accessControlService.canAccessCustomer(user, id)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(customerService.getVisibleCostCenters(id));
    }

    public static class CustomerCreateRequest {
        public Customer customer;
        public de.votian.services.entity.Company company;
        public de.votian.services.entity.User user;
        public String password;
    }

    public static class CustomerUpdateRequest {
        public Customer customer;
        public de.votian.services.entity.Company company;
        public de.votian.services.entity.User user;
    }
}
