<?php

namespace App\Http\Controllers\Api\Mobile;

use App\Http\Controllers\Controller;
use App\Models\Workspace;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;

/**
 * Mobile workspace endpoints.
 *
 * Cover the four flows the Flutter app needs to manage workspaces:
 *   - list every workspace the user is a member of (for the workspace
 *     switcher bottom sheet)
 *   - read the full detail of one workspace (settings screen)
 *   - create a new workspace (the seller's "Add workspace" button)
 *   - update editable workspace fields (name / industry / timezone / logo)
 *   - switch which workspace is the user's active one (every request
 *     scopes to active_workspace_id, so this is what controls scope)
 *
 * Mirrors the web Livewire `WorkspaceSwitcher` semantics:
 *   - creator is auto-attached as 'owner' with status='online'
 *   - switching busts the cached workspace context for both old + new
 *     workspace ids so the next request sees the freshly-resolved row
 *   - update is owner/admin only
 */
class WorkspacesController extends Controller
{
    /**
     * GET /api/v1/mobile/workspaces
     * Every workspace the authenticated user is a member of.
     * Used by the Flutter workspace switcher.
     */
    public function index(Request $request): JsonResponse
    {
        $user = $request->user();

        $rows = $user->workspaces()
            ->withPivot('role', 'status')
            ->orderBy('workspaces.name')
            ->get();

        $active = (int) ($user->active_workspace_id ?? 0);

        return response()->json([
            'data' => $rows->map(fn (Workspace $w) => [
                'id'         => $w->id,
                'uuid'       => $w->uuid,
                'name'       => $w->name,
                'slug'       => $w->slug,
                'logo_url'   => $w->logo_path ? asset('storage/' . $w->logo_path) : null,
                'industry'   => $w->industry,
                'team_size'  => $w->team_size,
                'timezone'   => $w->timezone,
                'your_role'  => $w->pivot->role ?? null,
                'is_active'  => $w->id === $active,
                'created_at' => $w->created_at?->toIso8601String(),
            ])->values()->all(),
            'meta' => [
                'active_workspace_id' => $active ?: null,
                'total'               => $rows->count(),
            ],
        ]);
    }

    /**
     * GET /api/v1/mobile/workspaces/{id}
     * Full detail for one workspace — only if the caller is a member.
     */
    public function show(Request $request, int $id): JsonResponse
    {
        $user = $request->user();

        if (!$user->workspaces()->where('workspaces.id', $id)->exists()) {
            return response()->json(['message' => 'Workspace not found.'], 404);
        }

        $workspace = Workspace::withCount([
            'contacts', 'conversations', 'emailAccounts', 'campaigns', 'workflows',
        ])->with(['subscription.plan'])->find($id);

        if (!$workspace) {
            return response()->json(['message' => 'Workspace not found.'], 404);
        }

        return response()->json([
            'data' => $this->shapeWorkspace($workspace, $user),
        ]);
    }

    /**
     * POST /api/v1/mobile/workspaces
     * Body: { name, industry?, team_size?, timezone? }
     *
     * Creates a workspace, attaches the caller as owner, and (by default)
     * switches the caller's active_workspace_id to the new row. The
     * client can opt out of the auto-switch by passing `switch=false`
     * — useful for a "create and add team later" flow that doesn't yank
     * the user out of their current workspace.
     */
    public function store(Request $request): JsonResponse
    {
        $user = $request->user();

        $data = Validator::make($request->all(), [
            'name'      => ['required', 'string', 'max:100'],
            'industry'  => ['nullable', 'string', 'max:50'],
            'team_size' => ['nullable', 'string', 'max:20'],
            'timezone'  => ['nullable', 'string', 'max:50'],
            'switch'    => ['sometimes', 'boolean'],
        ])->validate();

        $autoSwitch = (bool) ($data['switch'] ?? true);

        $workspace = DB::transaction(function () use ($data, $user, $autoSwitch) {
            $w = Workspace::create([
                'name'                 => $data['name'],
                'industry'             => $data['industry'] ?? null,
                'team_size'            => $data['team_size'] ?? null,
                'timezone'             => $data['timezone'] ?? null,
                'onboarding_step'      => 2,
                'onboarding_completed' => false,
            ]);

            // Attach the caller as the workspace owner — without this
            // attach the caller wouldn't even be allowed to read their
            // own newly-created workspace (the membership check is the
            // gate everywhere else).
            $w->members()->attach($user->id, [
                'role'   => 'owner',
                'status' => 'online',
            ]);

            if ($autoSwitch) {
                Cache::forget("workspace:{$user->id}:{$user->active_workspace_id}");
                $user->update(['active_workspace_id' => $w->id]);
                Cache::forget("workspace:{$user->id}:{$w->id}");
            }

            return $w;
        });

        return response()->json([
            'message' => __('Workspace created.'),
            'data'    => $this->shapeWorkspace(
                $workspace->loadCount(['contacts', 'conversations', 'emailAccounts', 'campaigns', 'workflows']),
                $user,
            ),
        ], 201);
    }

    /**
     * PUT /api/v1/mobile/workspaces/{id}
     * Body: any subset of { name, industry, team_size, timezone, logo_url, settings }
     *
     * Owners + admins only. Other roles get 403 — agents/viewers can
     * read a workspace but not rename it.
     */
    public function update(Request $request, int $id): JsonResponse
    {
        $user = $request->user();

        $membership = $user->workspaces()
            ->where('workspaces.id', $id)
            ->first();

        if (!$membership) {
            return response()->json(['message' => 'Workspace not found.'], 404);
        }

        $role = $membership->pivot?->role;
        if (!in_array($role, ['owner', 'admin'], true)) {
            return response()->json([
                'message' => 'Only owners and admins can update workspace settings.',
            ], 403);
        }

        $data = Validator::make($request->all(), [
            'name'      => ['sometimes', 'required', 'string', 'max:100'],
            'industry'  => ['sometimes', 'nullable', 'string', 'max:50'],
            'team_size' => ['sometimes', 'nullable', 'string', 'max:20'],
            'timezone'  => ['sometimes', 'nullable', 'string', 'max:50'],
            'settings'  => ['sometimes', 'array'],
        ])->validate();

        $workspace = Workspace::find($id);
        if (!$workspace) {
            return response()->json(['message' => 'Workspace not found.'], 404);
        }

        $workspace->fill($data)->save();

        // Bust the WorkspaceMiddleware cache so the next request sees
        // the new name/timezone instead of the 15-second-cached copy.
        Cache::forget("workspace:{$user->id}:{$id}");

        return response()->json([
            'message' => __('Workspace updated.'),
            'data'    => $this->shapeWorkspace(
                $workspace->loadCount(['contacts', 'conversations', 'emailAccounts', 'campaigns', 'workflows']),
                $user,
            ),
        ]);
    }

    /**
     * DELETE /api/v1/mobile/workspaces/{id}
     * Body: { name_confirmation: "<workspace name>", password: "<account password>" }
     *
     * Owner-only destructive action. Mirrors the web Livewire delete flow:
     *   - require typed workspace-name confirmation (prevents fat-finger)
     *   - require the user's account password (re-auth for a destructive op)
     *   - delete the logo file from public storage
     *   - clear active_workspace_id on every member pointing at this workspace
     *     (Eloquent SoftDeletes hides it from the user's workspace list)
     *   - soft-delete the workspace itself
     *   - re-point the caller's active_workspace_id at another workspace if
     *     they have one (so the next mobile request still resolves), otherwise
     *     null so the app routes them to onboarding
     *
     * Returns 422 on confirmation failures, 403 if not owner, 404 if not a
     * member.
     */
    public function destroy(Request $request, int $id): JsonResponse
    {
        $user = $request->user();

        $membership = $user->workspaces()->where('workspaces.id', $id)->first();
        if (! $membership) {
            return response()->json(['message' => 'Workspace not found.'], 404);
        }

        if (($membership->pivot?->role ?? null) !== 'owner') {
            return response()->json([
                'message' => 'Only the workspace owner can delete it.',
            ], 403);
        }

        $data = Validator::make($request->all(), [
            'name_confirmation' => ['required', 'string'],
            'password'          => ['required', 'string'],
        ])->validate();

        $workspace = Workspace::find($id);
        if (! $workspace) {
            return response()->json(['message' => 'Workspace not found.'], 404);
        }

        if ($data['name_confirmation'] !== $workspace->name) {
            return response()->json([
                'message' => 'Workspace name does not match. Type the exact name to confirm.',
                'errors'  => ['name_confirmation' => ['Workspace name does not match.']],
            ], 422);
        }

        if (! Hash::check($data['password'], $user->password)) {
            return response()->json([
                'message' => 'Incorrect account password.',
                'errors'  => ['password' => ['Incorrect account password.']],
            ], 422);
        }

        $nextWorkspaceId = DB::transaction(function () use ($workspace, $user) {
            if ($workspace->logo_path && Storage::disk('public')->exists($workspace->logo_path)) {
                Storage::disk('public')->delete($workspace->logo_path);
            }

            $memberIds = $workspace->members()->pluck('users.id');
            \App\Models\User::whereIn('id', $memberIds)
                ->where('active_workspace_id', $workspace->id)
                ->update(['active_workspace_id' => null]);

            $workspace->delete();

            // Pick any remaining workspace the caller still belongs to so
            // their next request has a valid scope. Refresh to bypass the
            // stale relationship cache that still includes the soft-deleted
            // row otherwise.
            $next = $user->fresh()->workspaces()->first();
            if ($next) {
                $user->update(['active_workspace_id' => $next->id]);
                Cache::forget("workspace:{$user->id}:{$next->id}");
                return $next->id;
            }

            return null;
        });

        Cache::forget("workspace:{$user->id}:{$id}");

        return response()->json([
            'message' => __('Workspace deleted.'),
            'data'    => [
                'deleted_workspace_id'    => $id,
                'next_active_workspace_id' => $nextWorkspaceId,
            ],
        ]);
    }

    /**
     * POST /api/v1/mobile/workspaces/{id}/switch
     * Sets the caller's active_workspace_id. Membership-checked — you
     * cannot switch INTO a workspace you don't belong to (no privilege
     * escalation by guessing an id).
     */
    public function switchActive(Request $request, int $id): JsonResponse
    {
        $user = $request->user();

        if (!$user->workspaces()->where('workspaces.id', $id)->exists()) {
            return response()->json(['message' => 'You do not have access to that workspace.'], 403);
        }

        if ((int) $user->active_workspace_id === (int) $id) {
            return response()->json([
                'message'  => __('Already on this workspace.'),
                'data'     => ['active_workspace_id' => (int) $id],
            ]);
        }

        Cache::forget("workspace:{$user->id}:{$user->active_workspace_id}");
        $user->update(['active_workspace_id' => $id]);
        Cache::forget("workspace:{$user->id}:{$id}");

        return response()->json([
            'message' => __('Switched workspace.'),
            'data'    => ['active_workspace_id' => (int) $id],
        ]);
    }

    /**
     * Shared shape used by show / store / update so the client sees the
     * same fields regardless of which endpoint produced the row.
     */
    private function shapeWorkspace(Workspace $w, $user): array
    {
        $userRole = method_exists($user, 'workspaceRole')
            ? $user->workspaceRole($w->id)
            : null;

        $sub = $w->subscription ?? null;

        return [
            'id'                   => $w->id,
            'uuid'                 => $w->uuid,
            'name'                 => $w->name,
            'slug'                 => $w->slug,
            'logo_url'             => $w->logo_path ? asset('storage/' . $w->logo_path) : null,
            'industry'             => $w->industry,
            'team_size'            => $w->team_size,
            'timezone'             => $w->timezone,
            'onboarding_completed' => (bool) $w->onboarding_completed,
            'onboarding_step'      => (int) ($w->onboarding_step ?? 0),
            'settings'             => is_array($w->settings) ? $w->settings : [],
            'business_hours'       => is_array($w->business_hours) ? $w->business_hours : null,
            'your_role'            => $userRole,
            'is_active'            => (int) $user->active_workspace_id === (int) $w->id,
            'counts'               => [
                'contacts'       => (int) ($w->contacts_count ?? 0),
                'conversations'  => (int) ($w->conversations_count ?? 0),
                'email_accounts' => (int) ($w->email_accounts_count ?? 0),
                'campaigns'      => (int) ($w->campaigns_count ?? 0),
                'workflows'      => (int) ($w->workflows_count ?? 0),
                'members'        => (int) $w->members()->count(),
            ],
            'subscription'         => $sub ? [
                'plan_name'          => $sub->plan?->name,
                'plan_slug'          => $sub->plan?->slug,
                'status'             => $sub->status,
                'billing_cycle'      => $sub->billing_cycle,
                'trial_ends_at'      => $sub->trial_ends_at?->toIso8601String(),
                'current_period_end' => $sub->current_period_end?->toIso8601String(),
            ] : null,
            'created_at'           => $w->created_at?->toIso8601String(),
        ];
    }
}
