<?php

namespace App\Http\Controllers\Api\Mobile;

use App\Http\Controllers\Controller;
use App\Models\Contact;
use App\Models\ContactList;
use App\Models\Segment;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

/**
 * Mobile audience selectors — populates the "Send to:" dropdowns in
 * the Flutter campaign composer.
 *
 * A campaign's `audience_type` column is one of:
 *   - 'all'      → every contact in the workspace
 *   - 'list'     → one ContactList (static, manually managed)
 *   - 'segment'  → one Segment (dynamic, rules-based JSON)
 *
 * This controller exposes both selector lists in one round-trip plus
 * a counts endpoint the composer uses to render "12,408 recipients"
 * under the picker once a choice is made.
 *
 * Endpoints (mounted under /api/v1/mobile/campaigns):
 *   GET /audience/options             { lists, segments, all_count }
 *   GET /audience/count?type=&id=     { count }
 *   GET /audience/lists               paginated contact lists
 *   GET /audience/segments            paginated segments
 */
class CampaignAudienceController extends Controller
{
    /**
     * GET /audience/options
     *
     * Returns every selectable audience in a single payload so the
     * composer can render the picker without a chain of requests.
     * Limited to 100 of each to keep the payload bounded — workspaces
     * with hundreds of lists should switch to the paginated endpoints.
     */
    public function options(Request $request): JsonResponse
    {
        $workspaceId = $request->user()->active_workspace_id;
        if (!$workspaceId) {
            return response()->json([
                'data' => ['all_count' => 0, 'lists' => [], 'segments' => []],
            ]);
        }

        $allCount = Contact::where('workspace_id', $workspaceId)
            ->where(function ($q) {
                $q->where('is_subscribed', true)->orWhereNull('is_subscribed');
            })
            ->count();

        $lists = ContactList::where('workspace_id', $workspaceId)
            ->orderBy('name')
            ->limit(100)
            ->get(['id', 'name', 'description', 'contacts_count']);

        $segments = Segment::where('workspace_id', $workspaceId)
            ->orderBy('name')
            ->limit(100)
            ->get(['id', 'name', 'rules', 'is_dynamic', 'contacts_count']);

        return response()->json([
            'data' => [
                'all_count' => $allCount,
                'lists'     => $lists->map(fn (ContactList $l) => [
                    'id'             => $l->id,
                    'name'           => $l->name,
                    'description'    => $l->description,
                    'contacts_count' => (int) ($l->contacts_count ?? 0),
                ])->all(),
                'segments'  => $segments->map(fn (Segment $s) => [
                    'id'             => $s->id,
                    'name'           => $s->name,
                    'is_dynamic'     => (bool) $s->is_dynamic,
                    'contacts_count' => (int) ($s->contacts_count ?? 0),
                    'rules_summary'  => $this->summariseRules($s->rules),
                ])->all(),
            ],
        ]);
    }

    /**
     * GET /audience/count?type=list|segment|all&id={id?}
     *
     * Returns the recipient count for the selected audience so the
     * composer can show "Send to 4,231 contacts" before the user
     * commits. Counts are LIVE (not cached) — picking a dynamic
     * segment recomputes its rules against the current contacts.
     */
    public function count(Request $request): JsonResponse
    {
        $workspaceId = $request->user()->active_workspace_id;
        $type = (string) $request->query('type', 'all');
        $id = $request->query('id');

        if (!$workspaceId) {
            return response()->json(['data' => ['count' => 0]]);
        }

        if ($type === 'all') {
            $count = Contact::where('workspace_id', $workspaceId)
                ->where(function ($q) {
                    $q->where('is_subscribed', true)->orWhereNull('is_subscribed');
                })
                ->count();
            return response()->json(['data' => ['count' => $count, 'type' => 'all']]);
        }

        if ($type === 'list') {
            $list = ContactList::where('workspace_id', $workspaceId)->find($id);
            if (!$list) return response()->json(['message' => 'List not found.'], 404);
            return response()->json([
                'data' => [
                    'count' => (int) ($list->contacts_count ?? 0),
                    'type'  => 'list',
                    'id'    => $list->id,
                    'name'  => $list->name,
                ],
            ]);
        }

        if ($type === 'segment') {
            $segment = Segment::where('workspace_id', $workspaceId)->find($id);
            if (!$segment) return response()->json(['message' => 'Segment not found.'], 404);
            return response()->json([
                'data' => [
                    'count' => (int) ($segment->contacts_count ?? 0),
                    'type'  => 'segment',
                    'id'    => $segment->id,
                    'name'  => $segment->name,
                ],
            ]);
        }

        return response()->json(['message' => 'Invalid audience type.'], 422);
    }

    public function lists(Request $request): JsonResponse
    {
        $workspaceId = $request->user()->active_workspace_id;
        $perPage = min(max((int) $request->query('per_page', 25), 1), 100);

        $paginator = ContactList::where('workspace_id', $workspaceId)
            ->orderBy('name')
            ->paginate($perPage);

        return response()->json([
            'data' => collect($paginator->items())->map(fn (ContactList $l) => [
                'id'             => $l->id,
                'name'           => $l->name,
                'description'    => $l->description,
                'contacts_count' => (int) ($l->contacts_count ?? 0),
            ])->all(),
            'meta' => [
                'current_page' => $paginator->currentPage(),
                'per_page'     => $paginator->perPage(),
                'total'        => $paginator->total(),
                'has_more'     => $paginator->hasMorePages(),
            ],
        ]);
    }

    public function segments(Request $request): JsonResponse
    {
        $workspaceId = $request->user()->active_workspace_id;
        $perPage = min(max((int) $request->query('per_page', 25), 1), 100);

        $paginator = Segment::where('workspace_id', $workspaceId)
            ->orderBy('name')
            ->paginate($perPage);

        return response()->json([
            'data' => collect($paginator->items())->map(fn (Segment $s) => [
                'id'             => $s->id,
                'name'           => $s->name,
                'is_dynamic'     => (bool) $s->is_dynamic,
                'contacts_count' => (int) ($s->contacts_count ?? 0),
                'rules_summary'  => $this->summariseRules($s->rules),
            ])->all(),
            'meta' => [
                'current_page' => $paginator->currentPage(),
                'per_page'     => $paginator->perPage(),
                'total'        => $paginator->total(),
                'has_more'     => $paginator->hasMorePages(),
            ],
        ]);
    }

    /**
     * One-line summary of a Segment rules JSON for the composer's
     * dropdown. Stops the Flutter side from having to ship a rules
     * interpreter just to render a useful label.
     */
    private function summariseRules($rules): ?string
    {
        if (!$rules) return null;
        $arr = is_array($rules) ? $rules : json_decode((string) $rules, true);
        if (!is_array($arr) || empty($arr)) return null;
        $count = is_array($arr['conditions'] ?? null) ? count($arr['conditions']) : count($arr);
        return $count . ' ' . ($count === 1 ? 'rule' : 'rules');
    }
}
