<?php

namespace App\Policies\Disk;

use App\Models\Disk\DiskItem;
use App\Models\User;

class DiskItemPolicy
{
    /**
     * Determine if user can view any items.
     */
    public function viewAny(User $user): bool
    {
        return $user->hasAgency() && $user->hasAnyRole(['agency-owner', 'agency-manager', 'agency-staff']);
    }

    /**
     * Determine if user can view the item.
     */
    public function view(User $user, DiskItem $item): bool
    {
        // Super admin can view everything
        if ($user->isSuperAdmin()) {
            return true;
        }

        // Same agency check via folder
        if ($user->currentAgencyId() !== $item->folder->agency_id) {
            return false;
        }

        // Check folder permissions first
        if (!$user->can('view', $item->folder)) {
            return false;
        }

        // If item is public, allow access
        if ($item->is_public) {
            return true;
        }

        // Item creator can always view
        if ($item->created_by === $user->id) {
            return true;
        }

        // Agency owner and manager can view all
        return $user->hasAnyRole(['agency-owner', 'agency-manager']);
    }

    /**
     * Determine if user can create items.
     */
    public function create(User $user): bool
    {
        return $user->hasAgency() && $user->hasAnyRole(['agency-owner', 'agency-manager', 'agency-staff']);
    }

    /**
     * Determine if user can update the item.
     */
    public function update(User $user, DiskItem $item): bool
    {
        // Super admin can update everything
        if ($user->isSuperAdmin()) {
            return true;
        }

        // Same agency check via folder
        if ($user->currentAgencyId() !== $item->folder->agency_id) {
            return false;
        }

        // Check folder update permissions
        if (!$user->can('update', $item->folder)) {
            return false;
        }

        // Item creator can always update
        if ($item->created_by === $user->id) {
            return true;
        }

        // Agency owner and manager can update all
        return $user->hasAnyRole(['agency-owner', 'agency-manager']);
    }

    /**
     * Determine if user can delete the item.
     */
    public function delete(User $user, DiskItem $item): bool
    {
        // Super admin can delete everything
        if ($user->isSuperAdmin()) {
            return true;
        }

        // Same agency check via folder
        if ($user->currentAgencyId() !== $item->folder->agency_id) {
            return false;
        }

        // Item creator can delete
        if ($item->created_by === $user->id) {
            return true;
        }

        // Agency owner and manager can delete all
        return $user->hasAnyRole(['agency-owner', 'agency-manager']);
    }

    /**
     * Determine if user can restore the item.
     */
    public function restore(User $user, DiskItem $item): bool
    {
        return $this->delete($user, $item);
    }

    /**
     * Determine if user can permanently delete the item.
     */
    public function forceDelete(User $user, DiskItem $item): bool
    {
        return $user->isSuperAdmin() ||
            ($user->currentAgencyId() === $item->folder->agency_id && $user->hasRole('agency-owner'));
    }

    /**
     * Determine if user can download the item.
     */
    public function download(User $user, DiskItem $item): bool
    {
        // Anyone who can view can download
        return $this->view($user, $item);
    }

    /**
     * Determine if user can approve the item.
     */
    public function approve(User $user, DiskItem $item): bool
    {
        // Super admin can approve everything
        if ($user->isSuperAdmin()) {
            return true;
        }

        // Same agency check via folder
        if ($user->currentAgencyId() !== $item->folder->agency_id) {
            return false;
        }

        // Only managers and owners can approve
        return $user->hasAnyRole(['agency-owner', 'agency-manager']);
    }

    /**
     * Determine if user can feature the item.
     */
    public function feature(User $user, DiskItem $item): bool
    {
        // Super admin can feature everything
        if ($user->isSuperAdmin()) {
            return true;
        }

        // Same agency check via folder
        if ($user->currentAgencyId() !== $item->folder->agency_id) {
            return false;
        }

        // Only managers and owners can feature
        return $user->hasAnyRole(['agency-owner', 'agency-manager']);
    }

    /**
     * Determine if user can move the item to another folder.
     */
    public function move(User $user, DiskItem $item): bool
    {
        // Super admin can move everything
        if ($user->isSuperAdmin()) {
            return true;
        }

        // Same agency check via folder
        if ($user->currentAgencyId() !== $item->folder->agency_id) {
            return false;
        }

        // Item creator can move
        if ($item->created_by === $user->id) {
            return true;
        }

        // Agency owner and manager can move
        return $user->hasAnyRole(['agency-owner', 'agency-manager']);
    }

    /**
     * Determine if user can upload a new version of the item.
     */
    public function uploadVersion(User $user, DiskItem $item): bool
    {
        // Super admin can upload versions
        if ($user->isSuperAdmin()) {
            return true;
        }

        // Same agency check via folder
        if ($user->currentAgencyId() !== $item->folder->agency_id) {
            return false;
        }

        // Must be able to update the item
        if (!$this->update($user, $item)) {
            return false;
        }

        // Item creator can upload versions
        if ($item->created_by === $user->id) {
            return true;
        }

        // Agency owner and manager can upload versions
        return $user->hasAnyRole(['agency-owner', 'agency-manager']);
    }

    /**
     * Determine if user can view version history.
     */
    public function viewVersions(User $user, DiskItem $item): bool
    {
        // Anyone who can view the item can view version history
        return $this->view($user, $item);
    }

    /**
     * Determine if user can restore a previous version.
     */
    public function restoreVersion(User $user, DiskItem $item): bool
    {
        // Super admin can restore versions
        if ($user->isSuperAdmin()) {
            return true;
        }

        // Same agency check via folder
        if ($user->currentAgencyId() !== $item->folder->agency_id) {
            return false;
        }

        // Item creator can restore versions
        if ($item->created_by === $user->id) {
            return true;
        }

        // Only agency owner and manager can restore versions
        return $user->hasAnyRole(['agency-owner', 'agency-manager']);
    }

    /**
     * Determine if user can delete a specific version.
     */
    public function deleteVersion(User $user, DiskItem $item): bool
    {
        // Super admin can delete versions
        if ($user->isSuperAdmin()) {
            return true;
        }

        // Same agency check via folder
        if ($user->currentAgencyId() !== $item->folder->agency_id) {
            return false;
        }

        // Can't delete the latest version
        if ($item->is_latest_version) {
            return false;
        }

        // Item creator can delete old versions
        if ($item->created_by === $user->id) {
            return true;
        }

        // Only agency owner and manager can delete versions
        return $user->hasAnyRole(['agency-owner', 'agency-manager']);
    }

    /**
     * Determine if user can share the item.
     */
    public function share(User $user, DiskItem $item): bool
    {
        // Super admin can share everything
        if ($user->isSuperAdmin()) {
            return true;
        }

        // Same agency check via folder
        if ($user->currentAgencyId() !== $item->folder->agency_id) {
            return false;
        }

        // Must be able to view the item
        if (!$this->view($user, $item)) {
            return false;
        }

        // Item must be public or user must be creator
        if ($item->is_public || $item->created_by === $user->id) {
            return true;
        }

        // Agency owner and manager can share
        return $user->hasAnyRole(['agency-owner', 'agency-manager']);
    }

    /**
     * Determine if user can perform bulk actions.
     */
    public function bulkAction(User $user): bool
    {
        return $user->hasAnyRole(['agency-owner', 'agency-manager']);
    }

    /**
     * Determine if user can edit item metadata.
     */
    public function editMetadata(User $user, DiskItem $item): bool
    {
        return $this->update($user, $item);
    }

    /**
     * Determine if user can view item statistics.
     */
    public function viewStatistics(User $user, DiskItem $item): bool
    {
        // Super admin can view all statistics
        if ($user->isSuperAdmin()) {
            return true;
        }

        // Same agency check via folder
        if ($user->currentAgencyId() !== $item->folder->agency_id) {
            return false;
        }

        // Item creator can view statistics
        if ($item->created_by === $user->id) {
            return true;
        }

        // Agency owner and manager can view statistics
        return $user->hasAnyRole(['agency-owner', 'agency-manager']);
    }

    /**
     * Determine if user can use item in tours/pages.
     */
    public function useInContent(User $user, DiskItem $item): bool
    {
        // Must be able to view the item
        if (!$this->view($user, $item)) {
            return false;
        }

        // Item must be approved
        if (!$item->is_approved) {
            return false;
        }

        return true;
    }

    /**
     * Determine if user can change item visibility.
     */
    public function changeVisibility(User $user, DiskItem $item): bool
    {
        // Super admin can change visibility
        if ($user->isSuperAdmin()) {
            return true;
        }

        // Same agency check via folder
        if ($user->currentAgencyId() !== $item->folder->agency_id) {
            return false;
        }

        // Item creator can change visibility
        if ($item->created_by === $user->id) {
            return true;
        }

        // Only agency owner and manager can change visibility
        return $user->hasAnyRole(['agency-owner', 'agency-manager']);
    }
}
