package ba.unsa.etf.si.bbqms.ws.controllers;

import ba.unsa.etf.si.bbqms.admin_service.api.AdvertisementService;
import ba.unsa.etf.si.bbqms.auth_service.api.AuthService;
import ba.unsa.etf.si.bbqms.domain.Advertisement;
import ba.unsa.etf.si.bbqms.ws.models.AdvertisementDto;
import ba.unsa.etf.si.bbqms.ws.models.SimpleMessageDto;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;

@RestController
@RequestMapping("/api/v1/ads")
public class AdvertisementController {
    private final AdvertisementService advertisementService;
    private final AuthService authService;

    public AdvertisementController(final AdvertisementService advertisementService,
                                   final AuthService authService) {
        this.advertisementService = advertisementService;
        this.authService = authService;
    }

    @GetMapping("/media/{adId}")
    public ResponseEntity streamMedia(@PathVariable final long adId) {
        try {
            final Advertisement advertisement = this.advertisementService.findById(adId);
            final Resource resource = this.advertisementService.loadMedia(adId);
            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + advertisement.getFileName() + "\"")
                    .contentType(MediaType.parseMediaType(advertisement.getContentType()))
                    .body(resource);
        } catch (final Exception exception) {
            return ResponseEntity.notFound().build();
        }
    }

    @GetMapping("/{tenantCode}/active")
    public ResponseEntity listActiveAdvertisements(@PathVariable final String tenantCode) {
        try {
            final List<AdvertisementDto> ads = this.advertisementService.listActiveByTenant(tenantCode).stream()
                    .map(AdvertisementDto::fromEntity)
                    .toList();
            return ResponseEntity.ok().body(ads);
        } catch (final Exception exception) {
            return ResponseEntity.badRequest().body(new SimpleMessageDto(exception.getMessage()));
        }
    }

    @PostMapping("/{tenantCode}")
    @PreAuthorize("hasAnyRole('ROLE_SUPER_ADMIN', 'ROLE_BRANCH_ADMIN')")
    public ResponseEntity createAdvertisement(@PathVariable final String tenantCode,
                                              @RequestParam("file") final MultipartFile file,
                                              @RequestParam(value = "title", required = false) final String title,
                                              @RequestParam(value = "durationSeconds", required = false) final Integer durationSeconds,
                                              @RequestParam(value = "sortOrder", required = false) final Integer sortOrder,
                                              @RequestParam(value = "active", required = false) final Boolean active) {
        if (!this.authService.canChangeTenant(tenantCode)) {
            return ResponseEntity.badRequest().build();
        }

        try {
            final Advertisement created = this.advertisementService.create(
                    tenantCode,
                    file,
                    title,
                    durationSeconds,
                    sortOrder,
                    active
            );
            return ResponseEntity.ok().body(AdvertisementDto.fromEntity(created));
        } catch (final Exception exception) {
            return ResponseEntity.badRequest().body(new SimpleMessageDto(exception.getMessage()));
        }
    }

    @GetMapping("/{tenantCode}")
    @PreAuthorize("hasAnyRole('ROLE_SUPER_ADMIN', 'ROLE_BRANCH_ADMIN')")
    public ResponseEntity listAdvertisements(@PathVariable final String tenantCode) {
        if (!this.authService.canChangeTenant(tenantCode)) {
            return ResponseEntity.badRequest().build();
        }

        try {
            final List<AdvertisementDto> ads = this.advertisementService.listByTenant(tenantCode).stream()
                    .map(AdvertisementDto::fromEntity)
                    .toList();
            return ResponseEntity.ok().body(ads);
        } catch (final Exception exception) {
            return ResponseEntity.badRequest().body(new SimpleMessageDto(exception.getMessage()));
        }
    }

    @PutMapping("/{tenantCode}/{adId}")
    @PreAuthorize("hasAnyRole('ROLE_SUPER_ADMIN', 'ROLE_BRANCH_ADMIN')")
    public ResponseEntity updateAdvertisement(@PathVariable final String tenantCode,
                                              @PathVariable final long adId,
                                              @RequestBody final AdvertisementUpdateRequest request) {
        if (!this.authService.canChangeTenant(tenantCode)) {
            return ResponseEntity.badRequest().build();
        }

        try {
            final Advertisement updated = this.advertisementService.update(
                    tenantCode,
                    adId,
                    request.title(),
                    request.durationSeconds(),
                    request.sortOrder(),
                    request.active()
            );
            return ResponseEntity.ok().body(AdvertisementDto.fromEntity(updated));
        } catch (final Exception exception) {
            return ResponseEntity.badRequest().body(new SimpleMessageDto(exception.getMessage()));
        }
    }

    @DeleteMapping("/{tenantCode}/{adId}")
    @PreAuthorize("hasAnyRole('ROLE_SUPER_ADMIN', 'ROLE_BRANCH_ADMIN')")
    public ResponseEntity deleteAdvertisement(@PathVariable final String tenantCode,
                                              @PathVariable final long adId) {
        if (!this.authService.canChangeTenant(tenantCode)) {
            return ResponseEntity.badRequest().build();
        }

        try {
            this.advertisementService.delete(tenantCode, adId);
            return ResponseEntity.ok().body(new SimpleMessageDto("Deleted advertisement with id: " + adId));
        } catch (final Exception exception) {
            return ResponseEntity.badRequest().body(new SimpleMessageDto(exception.getMessage()));
        }
    }

    public record AdvertisementUpdateRequest(String title,
                                             Integer durationSeconds,
                                             Integer sortOrder,
                                             Boolean active) {
    }
}
