package de.cannamanage.api.controller;

import de.cannamanage.api.dto.grow.*;
import de.cannamanage.domain.entity.*;
import de.cannamanage.domain.enums.GrowStage;
import de.cannamanage.domain.enums.SensorReadingType;
import de.cannamanage.service.GrowCalendarService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.UUID;

@RestController
@RequestMapping("/api/v1/grow")
@RequiredArgsConstructor
@Tag(name = "Grow Calendar", description = "Grow lifecycle management with sensors, photos, and feeding")
public class GrowCalendarController {

    private final GrowCalendarService growCalendarService;

    @GetMapping
    @Operation(summary = "List all grow entries")
    @PreAuthorize("hasRole('ADMIN') or @staffPermissions.has(authentication, T(de.cannamanage.domain.enums.StaffPermission).VIEW_STOCK)")
    public ResponseEntity<List<GrowEntryResponse>> listGrowEntries() {
        List<GrowEntryResponse> entries = growCalendarService.getGrowEntries().stream()
                .map(this::toResponse)
                .toList();
        return ResponseEntity.ok(entries);
    }

    @PostMapping
    @Operation(summary = "Create a new grow entry")
    @PreAuthorize("hasRole('ADMIN') or @staffPermissions.has(authentication, T(de.cannamanage.domain.enums.StaffPermission).RECORD_STOCK_IN)")
    public ResponseEntity<GrowEntryResponse> createGrowEntry(@Valid @RequestBody CreateGrowEntryRequest request) {
        GrowEntry entry = growCalendarService.createGrowEntry(
                request.name(), request.strainId(), request.notes(), request.expectedHarvestAt());
        return ResponseEntity.status(HttpStatus.CREATED).body(toResponse(entry));
    }

    @GetMapping("/{id}")
    @Operation(summary = "Get grow entry detail with stages, sensors, photos, feedings")
    @PreAuthorize("hasRole('ADMIN') or @staffPermissions.has(authentication, T(de.cannamanage.domain.enums.StaffPermission).VIEW_STOCK)")
    public ResponseEntity<GrowEntryDetailResponse> getGrowEntry(@PathVariable UUID id) {
        GrowEntry entry = growCalendarService.getGrowEntry(id);
        List<GrowStageLog> stages = growCalendarService.getStageLogs(id);
        List<SensorReading> sensors = growCalendarService.getSensorReadings(id);
        List<GrowPhoto> photos = growCalendarService.getPhotos(id);
        List<FeedingLog> feedings = growCalendarService.getFeedingLogs(id);

        GrowEntryDetailResponse detail = new GrowEntryDetailResponse(
                entry.getId(), entry.getName(), entry.getStrainId(), entry.getStatus(),
                entry.getStartedAt(), entry.getExpectedHarvestAt(), entry.getActualHarvestAt(),
                entry.getHarvestedGrams(), entry.getLinkedBatchId(), entry.getNotes(),
                stages.stream().map(this::toStageResponse).toList(),
                sensors.stream().map(this::toSensorResponse).toList(),
                photos.stream().map(this::toPhotoResponse).toList(),
                feedings.stream().map(this::toFeedingResponse).toList()
        );
        return ResponseEntity.ok(detail);
    }

    @PutMapping("/{id}/stage")
    @Operation(summary = "Advance to next stage")
    @PreAuthorize("hasRole('ADMIN') or @staffPermissions.has(authentication, T(de.cannamanage.domain.enums.StaffPermission).RECORD_STOCK_IN)")
    public ResponseEntity<GrowEntryResponse> advanceStage(@PathVariable UUID id, @Valid @RequestBody AdvanceStageRequest request) {
        GrowEntry entry = growCalendarService.advanceStage(id, request.stage());
        return ResponseEntity.ok(toResponse(entry));
    }

    @PostMapping("/{id}/sensors")
    @Operation(summary = "Add sensor reading")
    @PreAuthorize("hasRole('ADMIN') or @staffPermissions.has(authentication, T(de.cannamanage.domain.enums.StaffPermission).RECORD_STOCK_IN)")
    public ResponseEntity<SensorReadingResponse> addSensorReading(@PathVariable UUID id, @Valid @RequestBody AddSensorReadingRequest request) {
        SensorReading reading = growCalendarService.addSensorReading(id, request.readingType(), request.value(), request.unit());
        return ResponseEntity.status(HttpStatus.CREATED).body(toSensorResponse(reading));
    }

    @PostMapping("/{id}/photos")
    @Operation(summary = "Add photo")
    @PreAuthorize("hasRole('ADMIN') or @staffPermissions.has(authentication, T(de.cannamanage.domain.enums.StaffPermission).RECORD_STOCK_IN)")
    public ResponseEntity<GrowPhotoResponse> addPhoto(@PathVariable UUID id, @Valid @RequestBody AddPhotoRequest request) {
        GrowPhoto photo = growCalendarService.addPhoto(id, request.filePath(), request.caption());
        return ResponseEntity.status(HttpStatus.CREATED).body(toPhotoResponse(photo));
    }

    @PostMapping("/{id}/feedings")
    @Operation(summary = "Add feeding log")
    @PreAuthorize("hasRole('ADMIN') or @staffPermissions.has(authentication, T(de.cannamanage.domain.enums.StaffPermission).RECORD_STOCK_IN)")
    public ResponseEntity<FeedingLogResponse> addFeedingLog(@PathVariable UUID id, @Valid @RequestBody AddFeedingLogRequest request) {
        FeedingLog feeding = growCalendarService.addFeedingLog(id,
                request.nutrientName(), request.amountMl(), request.waterLiters(),
                request.phAfter(), request.ecAfter(), request.notes());
        return ResponseEntity.status(HttpStatus.CREATED).body(toFeedingResponse(feeding));
    }

    @PutMapping("/{id}/harvest")
    @Operation(summary = "Complete harvest and link to batch")
    @PreAuthorize("hasRole('ADMIN') or @staffPermissions.has(authentication, T(de.cannamanage.domain.enums.StaffPermission).RECORD_STOCK_IN)")
    public ResponseEntity<GrowEntryResponse> completeHarvest(@PathVariable UUID id, @Valid @RequestBody CompleteHarvestRequest request) {
        GrowEntry entry = growCalendarService.completeHarvest(id, request.harvestedGrams(), request.linkedBatchId());
        return ResponseEntity.ok(toResponse(entry));
    }

    // --- Mapping helpers ---

    private GrowEntryResponse toResponse(GrowEntry e) {
        return new GrowEntryResponse(e.getId(), e.getName(), e.getStrainId(), e.getStatus(),
                e.getStartedAt(), e.getExpectedHarvestAt(), e.getActualHarvestAt(),
                e.getHarvestedGrams(), e.getLinkedBatchId(), e.getNotes());
    }

    private GrowStageLogResponse toStageResponse(GrowStageLog s) {
        return new GrowStageLogResponse(s.getId(), s.getStage(), s.getStartedAt(), s.getEndedAt(), s.getNotes());
    }

    private SensorReadingResponse toSensorResponse(SensorReading r) {
        return new SensorReadingResponse(r.getId(), r.getReadingType(), r.getValue(), r.getUnit(), r.getRecordedAt());
    }

    private GrowPhotoResponse toPhotoResponse(GrowPhoto p) {
        return new GrowPhotoResponse(p.getId(), p.getFilePath(), p.getCaption(), p.getTakenAt());
    }

    private FeedingLogResponse toFeedingResponse(FeedingLog f) {
        return new FeedingLogResponse(f.getId(), f.getNutrientName(), f.getAmountMl(),
                f.getWaterLiters(), f.getPhAfter(), f.getEcAfter(), f.getFedAt(), f.getNotes());
    }
}
