using TornadoAce_CJOnStyle.Domain;

namespace TornadoAce_CJOnStyle.Services
{
    public sealed class MockTornadoSceneAdapter : ITornadoSceneAdapter
    {
        private readonly AutomationWorkspace workspace;

        public MockTornadoSceneAdapter(AutomationWorkspace workspace)
        {
            this.workspace = workspace;
        }

        public Task<SceneDataSnapshot> CreateOrUpdateSceneAsync(
            CueSheetRecord cueSheet,
            SceneTemplateDefinition template,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var visibleObjects = BuildVisibleTextObjects(cueSheet, template);
            return Task.FromResult(BuildSnapshot(cueSheet, template, visibleObjects));
        }

        public Task<SceneDataSnapshot> ExtractSceneDataAsync(string scenePath, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var cueSheet = FindCueSheet(scenePath) ?? workspace.CueSheets.First();
            var visibleObjects = BuildVisibleTextObjects(cueSheet, workspace.ActiveTemplate);

            if (cueSheet.CueSheetId.EndsWith("-002", StringComparison.Ordinal))
            {
                visibleObjects["TXT_PRICE"] = "79,900원";
            }

            if (cueSheet.CueSheetId.EndsWith("-003", StringComparison.Ordinal))
            {
                visibleObjects["TXT_PROMOTION"] = "앱 주문 추가 적립 ※";
            }

            return Task.FromResult(BuildSnapshot(cueSheet, workspace.ActiveTemplate, visibleObjects));
        }

        public IReadOnlyList<TornadoAdapterCheck> GetAdapterChecks()
        {
            return
            [
                new TornadoAdapterCheck("SDK-01", "Tornado2 Scene 생성", "Mock", "CreateOrUpdateSceneAsync"),
                new TornadoAdapterCheck("SDK-02", "Scene Data API 추출", "Mock", "ExtractSceneDataAsync"),
                new TornadoAdapterCheck("SDK-03", "Tornado3 전환 경계", "준비", "ITornadoSceneAdapter 유지")
            ];
        }

        private CueSheetRecord? FindCueSheet(string scenePath)
        {
            return workspace.CueSheets.FirstOrDefault(cueSheet => scenePath.Contains(cueSheet.BroadcastTime.ToString("HHmm"), StringComparison.Ordinal));
        }

        private static SceneDataSnapshot BuildSnapshot(
            CueSheetRecord cueSheet,
            SceneTemplateDefinition template,
            IReadOnlyDictionary<string, string> visibleObjects)
        {
            var sceneName = $"{template.TemplateId}_{cueSheet.BroadcastTime:HHmm}.tscn";
            return new SceneDataSnapshot(sceneName, template.TemplateId, visibleObjects, [BuildImagePath(cueSheet)]);
        }

        private static Dictionary<string, string> BuildVisibleTextObjects(CueSheetRecord cueSheet, SceneTemplateDefinition template)
        {
            return template.Mappings.ToDictionary(
                mapping => mapping.SceneObjectName,
                mapping => ReadCueSheetValue(cueSheet, mapping.CueSheetField),
                StringComparer.OrdinalIgnoreCase);
        }

        private static string ReadCueSheetValue(CueSheetRecord cueSheet, string fieldName)
        {
            return fieldName switch
            {
                "programTitle" => cueSheet.ProgramTitle,
                "productName" => cueSheet.ProductName,
                "priceText" => cueSheet.PriceText,
                "compositionText" => cueSheet.CompositionText,
                "promotionText" => cueSheet.PromotionText,
                _ => string.Empty
            };
        }

        private static string BuildImagePath(CueSheetRecord cueSheet)
        {
            var directoryName = new string(cueSheet.ProductName
                .Select(character => char.IsLetterOrDigit(character) ? character : '_')
                .ToArray()).Trim('_');

            return $@"D:\CJOnStyle\Products\{directoryName}\main.png";
        }
    }

    public sealed record TornadoAdapterCheck(
        string CheckId,
        string Name,
        string Status,
        string Evidence);
}
