import 'dart:math' as math;

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import '../../../app/theme/mapflow_theme.dart';
import '../data/voice_experiences_repository.dart';
import '../domain/place_models.dart';

class AdminVoiceExperiencesScreen extends StatefulWidget {
  const AdminVoiceExperiencesScreen({super.key});

  @override
  State<AdminVoiceExperiencesScreen> createState() =>
      _AdminVoiceExperiencesScreenState();
}

class _AdminVoiceExperiencesScreenState
    extends State<AdminVoiceExperiencesScreen> {
  late final Future<List<VoiceExperienceDebug>> _future = context
      .read<VoiceExperiencesRepository>()
      .fetchVoiceExperiences();

  @override
  Widget build(BuildContext context) {
    final tokens = context.mapflowTokens;

    return Scaffold(
      backgroundColor: tokens.darkSurface,
      appBar: AppBar(title: const Text('Отзывы')),
      body: FutureBuilder<List<VoiceExperienceDebug>>(
        future: _future,
        builder: (context, snapshot) {
          if (snapshot.connectionState != ConnectionState.done) {
            return const Center(child: CircularProgressIndicator());
          }
          if (snapshot.hasError) {
            return Center(child: Text(snapshot.error.toString()));
          }

          final reviews = snapshot.data ?? const <VoiceExperienceDebug>[];
          return ListView.separated(
            padding: const EdgeInsets.all(12),
            itemCount: reviews.length,
            separatorBuilder: (_, _) => const SizedBox(height: 8),
            itemBuilder: (context, index) {
              return _AdminVoiceExperienceRow(review: reviews[index]);
            },
          );
        },
      ),
    );
  }
}

class _AdminVoiceExperienceRow extends StatelessWidget {
  const _AdminVoiceExperienceRow({required this.review});

  final VoiceExperienceDebug review;

  @override
  Widget build(BuildContext context) {
    final selectedTags = _selectedAdminTags(review.analysis);
    final tokens = context.mapflowTokens;

    return Material(
      color: tokens.mapPanel,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(tokens.panelRadius),
        side: BorderSide(color: tokens.mapPanelBorder),
      ),
      child: Padding(
        padding: const EdgeInsets.all(12),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                Expanded(
                  child: Text(
                    review.placeName,
                    maxLines: 1,
                    overflow: TextOverflow.ellipsis,
                    style: const TextStyle(fontWeight: FontWeight.w900),
                  ),
                ),
                Text(
                  review.status,
                  style: const TextStyle(fontWeight: FontWeight.w700),
                ),
              ],
            ),
            const SizedBox(height: 6),
            Text(
              '${review.userName} · ${review.durationSeconds}s',
              maxLines: 1,
              overflow: TextOverflow.ellipsis,
              style: TextStyle(color: Theme.of(context).colorScheme.outline),
            ),
            if (review.transcript?.trim().isNotEmpty == true) ...[
              const SizedBox(height: 8),
              Text(
                review.transcript!,
                maxLines: 3,
                overflow: TextOverflow.ellipsis,
              ),
            ],
            const SizedBox(height: 10),
            _AdminOntologySnowflake(selectedTags: selectedTags),
          ],
        ),
      ),
    );
  }
}

class _AdminOntologySnowflake extends StatelessWidget {
  const _AdminOntologySnowflake({required this.selectedTags});

  final Set<String> selectedTags;

  static const _axes = [
    _AdminOntologyAxis(
      id: 'energy',
      label: 'энергия',
      angle: -math.pi / 2,
      leaves: [
        _AdminOntologyLeaf('calm', 'спокойное', -0.22),
        _AdminOntologyLeaf('dynamic', 'живое', 0.22),
      ],
    ),
    _AdminOntologyAxis(
      id: 'privacy',
      label: 'приватность',
      angle: -math.pi / 2 + math.pi * 2 / 5,
      leaves: [
        _AdminOntologyLeaf('intimate', 'камерное', -0.2),
        _AdminOntologyLeaf('open', 'открытое', 0.2),
      ],
    ),
    _AdminOntologyAxis(
      id: 'function',
      label: 'сценарий',
      angle: -math.pi / 2 + math.pi * 4 / 5,
      leaves: [
        _AdminOntologyLeaf('reset', 'выдохнуть', -0.25),
        _AdminOntologyLeaf('impress', 'впечатлить', 0),
        _AdminOntologyLeaf('transit', 'транзитное', 0.25),
      ],
    ),
    _AdminOntologyAxis(
      id: 'aesthetic',
      label: 'образ',
      angle: -math.pi / 2 + math.pi * 6 / 5,
      leaves: [
        _AdminOntologyLeaf('clean', 'чистое', -0.2),
        _AdminOntologyLeaf('expressive', 'выразительное', 0.2),
      ],
    ),
    _AdminOntologyAxis(
      id: 'sociality',
      label: 'социальность',
      angle: -math.pi / 2 + math.pi * 8 / 5,
      leaves: [
        _AdminOntologyLeaf('solo', 'для себя', -0.2),
        _AdminOntologyLeaf('group', 'для компании', 0.2),
      ],
    ),
  ];

  @override
  Widget build(BuildContext context) {
    final tokens = context.mapflowTokens;

    return SizedBox(
      height: 300,
      width: double.infinity,
      child: CustomPaint(
        painter: _AdminOntologySnowflakePainter(
          axes: _axes,
          selectedTags: selectedTags,
          tokens: tokens,
        ),
      ),
    );
  }
}

class _AdminOntologySnowflakePainter extends CustomPainter {
  const _AdminOntologySnowflakePainter({
    required this.axes,
    required this.selectedTags,
    required this.tokens,
  });

  final List<_AdminOntologyAxis> axes;
  final Set<String> selectedTags;
  final MapflowThemeTokens tokens;

  @override
  void paint(Canvas canvas, Size size) {
    final center = Offset(size.width / 2, size.height / 2);
    final radius = math.min(size.width, size.height);
    final axisRadius = radius * 0.25;
    final leafRadius = radius * 0.43;

    final baseLine = Paint()
      ..color = tokens.snowflakeLine
      ..strokeWidth = 1.3
      ..style = PaintingStyle.stroke;
    final selectedLine = Paint()
      ..color = tokens.danger
      ..strokeWidth = 2.2
      ..strokeCap = StrokeCap.round
      ..style = PaintingStyle.stroke;
    final node = Paint()..color = tokens.snowflakeNode;
    final selectedNode = Paint()..color = tokens.danger;
    final centerNode = Paint()..color = tokens.snowflakeCenter;

    canvas.drawCircle(center, 5, centerNode);
    _drawLabel(canvas, size, center + const Offset(0, 14), 'место', true);

    for (final axis in axes) {
      final axisOffset = Offset(math.cos(axis.angle), math.sin(axis.angle));
      final axisPoint = center + axisOffset * axisRadius;
      final hasSelectedLeaf = axis.leaves.any(
        (leaf) => selectedTags.contains('${axis.id}:${leaf.id}'),
      );

      canvas.drawLine(
        center,
        axisPoint,
        hasSelectedLeaf ? selectedLine : baseLine,
      );
      canvas.drawCircle(
        axisPoint,
        hasSelectedLeaf ? 5.5 : 4.5,
        hasSelectedLeaf ? selectedNode : node,
      );
      _drawLabel(
        canvas,
        size,
        axisPoint + axisOffset * 18,
        axis.label,
        hasSelectedLeaf,
        fontSize: 11,
      );

      for (final leaf in axis.leaves) {
        final leafAngle = axis.angle + leaf.angleOffset;
        final leafOffset = Offset(math.cos(leafAngle), math.sin(leafAngle));
        final leafPoint = center + leafOffset * leafRadius;
        final tag = '${axis.id}:${leaf.id}';
        final selected = selectedTags.contains(tag);

        canvas.drawLine(
          axisPoint,
          leafPoint,
          selected ? selectedLine : baseLine,
        );
        canvas.drawCircle(
          leafPoint,
          selected ? 8 : 5.5,
          selected ? selectedNode : node,
        );
        _drawLabel(
          canvas,
          size,
          leafPoint + leafOffset * 20,
          leaf.label,
          selected,
        );
      }
    }
  }

  void _drawLabel(
    Canvas canvas,
    Size size,
    Offset anchor,
    String label,
    bool selected, {
    double fontSize = 12,
  }) {
    final painter = TextPainter(
      text: TextSpan(
        text: label,
        style: TextStyle(
          color: selected ? tokens.danger : tokens.snowflakeLabel,
          fontSize: fontSize,
          fontWeight: selected ? FontWeight.w900 : FontWeight.w700,
          height: 1,
        ),
      ),
      textDirection: TextDirection.ltr,
      maxLines: 1,
    )..layout(maxWidth: 86);
    final dx = (anchor.dx - painter.width / 2).clamp(
      0.0,
      size.width - painter.width,
    );
    final dy = (anchor.dy - painter.height / 2).clamp(
      0.0,
      size.height - painter.height,
    );
    painter.paint(canvas, Offset(dx, dy));
  }

  @override
  bool shouldRepaint(covariant _AdminOntologySnowflakePainter oldDelegate) {
    return oldDelegate.selectedTags != selectedTags ||
        oldDelegate.tokens != tokens;
  }
}

class _AdminOntologyAxis {
  const _AdminOntologyAxis({
    required this.id,
    required this.label,
    required this.angle,
    required this.leaves,
  });

  final String id;
  final String label;
  final double angle;
  final List<_AdminOntologyLeaf> leaves;
}

class _AdminOntologyLeaf {
  const _AdminOntologyLeaf(this.id, this.label, this.angleOffset);

  final String id;
  final String label;
  final double angleOffset;
}

Set<String> _selectedAdminTags(Map<String, dynamic>? analysis) {
  final tags = analysis?['tags'];
  if (tags is! List) {
    return const {};
  }
  return tags.whereType<String>().toSet();
}
