package com.itdominator.api.controller;


import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.validation.annotation.Validated;
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.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.itdominator.api.dto.ThumbnailDto;
import com.itdominator.api.dto.ThumbnailSearchCriteria;
import com.itdominator.api.services.ThumbnailerService;

import jakarta.validation.Valid;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.Pattern;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;



@RestController
@EnableMethodSecurity(securedEnabled = true, prePostEnabled = true)
@RequiredArgsConstructor
@Slf4j
@Validated
public class ThumbnailerApiController {

    private final ThumbnailerService thumbnailerService;

    @Value("${videos.filter}")
    private final String[] videoFilter;


    @PreAuthorize("hasRole('User')")
    @PostMapping("/get-thumbnail/id/{id}")
    public ThumbnailDto getThumbnailById(
        @PathVariable
        @Min(value = 0L, message = "Can't be negative number...")
        @Max(value = 99999999L, message = "ID too large...") final int id
    ) {
        return thumbnailerService.getThumbnailById(id);
    }

    @PreAuthorize("hasRole('User')")
    @PostMapping("/get-thumbnail/hash/{fileHash}")
    public ThumbnailDto getThumbnailByHash(
        @Pattern(regexp = "[a-zA-Z0-9]{32}*$") @PathVariable("fileHash") final String fileHash
    ) {
        return thumbnailerService.getThumbnailByHash(fileHash);
    }


    @PreAuthorize("hasRole('User')")
    @PostMapping("/get-thumbnail")
    public ThumbnailDto getThumbnailByIdOrHashQuery(
        @Valid @RequestBody ThumbnailSearchCriteria criteria
    ) {
        return thumbnailerService.getThumbnailByIdOrHashQuery(criteria);
    }

    @PreAuthorize("hasRole('Admin')")
    @GetMapping("/get-all-thumbnails")
    public List<ThumbnailDto> getAllThumbnails() {
        return thumbnailerService.getAllThumbnails();
    }

    @PreAuthorize("hasRole('User')")
    @GetMapping("/temp-videos-list-test")
    public Set<String> getAllVideoFiles() {
        Set<Path> paths   = collectVideoFilePaths("/home/abaddon/Downloads");
        Set<String> files = new HashSet<>();

        generateThumbnails(paths);
        for (Path path : paths) {
            files.add( path.getFileName().toString() );
        }

        return files;
    }


    public Set<Path> collectVideoFilePaths(final String dir) {
        Set<Path> paths = new HashSet<>();

        try (DirectoryStream<Path> stream = Files.newDirectoryStream( Paths.get(dir) )) {
            for (Path path : stream) {
                if ( !Files.isDirectory(path) ) {
                    String target = path.getFileName().toString();
                    for (String filterItem : videoFilter) {
                        if ( target.endsWith(filterItem) ) {
                            paths.add(path);
                        }
                    }
                }
            }
        } catch (IOException e) {
            log.debug("Invalid path given to scan...");
        }

        return paths;
    }

    public void generateThumbnails(Set<Path> paths) {
        for (Path path : paths) {
            String fileName = path.getFileName().toString();
            String fileHash = DigestUtils.sha256Hex(fileName);
            generateThumbnail(path.toString(), "/home/abaddon/Downloads/tmp/" + fileHash + ".jpg","65%");
        }
    }



    // proc = subprocess.Popen([self.FFMPG_THUMBNLR, "-t", scrub_percent, "-s", "300", "-c", "jpg", "-i", full_path, "-o", hash_img_path])
    public void generateThumbnail(final String full_path, final String hash_img_path, final String scrub_percent) {
        try {
            ProcessBuilder pb = new ProcessBuilder("ffmpegthumbnailer", "-t", scrub_percent, "-s", "300", "-c", "jpg", "-i", full_path, "-o", hash_img_path);
            Process p = pb.start();
        } catch (Exception e) {
            log.debug("Thumbnail couldn't be generated...");
            // Note: Need supporting logic for failed loads. Maybe return empty byte[]
        }

    }

}
