import SwiftUI
import CoreImage.CIFilterBuiltins

struct WeekPlanShareView: View {
    let plan: WeekPlan
    let settings: AppSettings
    let dishes: [Dish]
    let tags: [Tag]

    static let a4LandscapeWidth: CGFloat = 3508
    static let a4LandscapeHeight: CGFloat = 2480

    private let shareURL = "https://mealmood.app"
    private let qrContext = CIContext()
    private let qrFilter = CIFilter.qrCodeGenerator()

    private var dayRange: ClosedRange<Int> {
        settings.includeWeekends ? 0...6 : 0...4
    }

    private var mealTypes: [MealType] {
        switch settings.mealWindowsEnum {
        case .dinnerOnly: return [.dinner]
        case .lunchOnly: return [.lunch]
        case .both: return [.lunch, .dinner]
        }
    }

    private var exportDateString: String {
        Date.now.formatted(date: .abbreviated, time: .omitted)
    }

    private var qrImage: UIImage? {
        qrFilter.setValue(Data(shareURL.utf8), forKey: "inputMessage")
        qrFilter.setValue("M", forKey: "inputCorrectionLevel")
        guard let outputImage = qrFilter.outputImage else { return nil }
        let transformed = outputImage.transformed(by: CGAffineTransform(scaleX: 10, y: 10))
        guard let cgImage = qrContext.createCGImage(transformed, from: transformed.extent) else { return nil }
        return UIImage(cgImage: cgImage)
    }

    var body: some View {
        ZStack {
            backgroundLayer

            VStack(alignment: .leading, spacing: 34) {
                headerBlock

                ZStack {
                    RoundedRectangle(cornerRadius: 30)
                        .fill(Color.white.opacity(0.62))
                    RoundedRectangle(cornerRadius: 30)
                        .stroke(Color.white.opacity(0.75), lineWidth: 2)

                    Grid(horizontalSpacing: 10, verticalSpacing: 10) {
                        GridRow {
                            gridHeaderCell("", day: nil)
                                .frame(minWidth: 220)
                            ForEach(Array(dayRange), id: \.self) { day in
                                gridHeaderCell(dayTitle(for: day), day: day)
                            }
                        }

                        ForEach(mealTypes, id: \.self) { mealType in
                            GridRow {
                                gridMealCell(mealTypeLabel(mealType), icon: mealType.icon, mealType: mealType)
                                    .frame(minWidth: 220)
                                ForEach(Array(dayRange), id: \.self) { day in
                                    gridDishCell(dishName(day: day, mealType: mealType), day: day)
                                }
                            }
                        }
                    }
                    .padding(18)
                }
                .shadow(color: Color(hex: "#DDAA99").opacity(0.18), radius: 26, x: 0, y: 16)

                Spacer()

                footerBlock
            }
            .padding(.horizontal, 84)
            .padding(.vertical, 72)
        }
        .frame(width: Self.a4LandscapeWidth, height: Self.a4LandscapeHeight)
    }

    private func dayTitle(for day: Int) -> String {
        let keys = ["day_mon", "day_tue", "day_wed", "day_thu", "day_fri", "day_sat", "day_sun"]
        let localizedDay = day >= 0 && day < keys.count ? NSLocalizedString(keys[day], comment: "") : ""
        let dayDate = plan.weekStartDate.addingDays(day)
        let dayNumber = Calendar.current.component(.day, from: dayDate)
        return "\(localizedDay) \(dayNumber)"
    }

    private func mealTypeLabel(_ mealType: MealType) -> String {
        mealType == .lunch ? String(localized: "lunch") : String(localized: "dinner")
    }

    private func dishName(day: Int, mealType: MealType) -> String {
        let slot = plan.slots.first { $0.dayOfWeek == day && $0.mealType == mealType.rawValue }
        guard let slot, let dishId = slot.dishId, let dish = dishes.first(where: { $0.id == dishId }) else {
            return "—"
        }
        return dish.name
    }

    private var backgroundLayer: some View {
        ZStack {
            LinearGradient(
                colors: [
                    Color(hex: "#FFEFE6"),
                    Color(hex: "#F1FBF5")
                ],
                startPoint: .topLeading,
                endPoint: .bottomTrailing
            )

            Circle()
                .fill(Color(hex: "#FFD6E2").opacity(0.55))
                .frame(width: 760, height: 760)
                .blur(radius: 20)
                .offset(x: -980, y: -760)

            Circle()
                .fill(Color(hex: "#CFF2E8").opacity(0.55))
                .frame(width: 680, height: 680)
                .blur(radius: 20)
                .offset(x: 1050, y: 760)

            GeometryReader { geo in
                Canvas { context, size in
                    let spacing: CGFloat = 80
                    var x: CGFloat = -size.height
                    while x < size.width {
                        var path = Path()
                        path.move(to: CGPoint(x: x, y: 0))
                        path.addLine(to: CGPoint(x: x + size.height, y: size.height))
                        context.stroke(path, with: .color(Color(hex: "#FFFFFF").opacity(0.26)), lineWidth: 1.2)
                        x += spacing
                    }
                }
                .frame(width: geo.size.width, height: geo.size.height)
            }
        }
    }

    private var headerBlock: some View {
        HStack(alignment: .center, spacing: 24) {
            AppIconPlaceholder(size: 84)

            VStack(alignment: .leading, spacing: 8) {
                Text("MealMood Premium")
                    .font(.system(size: 50, weight: .bold, design: .rounded))
                    .foregroundColor(.mealMoodTextPrimary)
                Text(String(localized: "share_week_title"))
                    .font(.system(size: 28, weight: .semibold, design: .rounded))
                    .foregroundColor(Color(hex: "#5D645F"))
            }

            Spacer()

            VStack(alignment: .trailing, spacing: 8) {
                Text(plan.weekStartDate.formattedWeekRange())
                    .font(.system(size: 36, weight: .bold, design: .rounded))
                    .foregroundColor(Color(hex: "#4A4F4B"))
                Text(exportDateString)
                    .font(.system(size: 24, weight: .medium, design: .rounded))
                    .foregroundColor(.mealMoodTextSecondary)
            }
        }
        .padding(.horizontal, 30)
        .padding(.vertical, 24)
        .background(Color.white.opacity(0.76))
        .clipShape(RoundedRectangle(cornerRadius: 24))
        .overlay(
            RoundedRectangle(cornerRadius: 24)
                .stroke(Color(hex: "#F3C4B5").opacity(0.7), lineWidth: 1)
        )
        .shadow(color: Color(hex: "#DDAA99").opacity(0.15), radius: 20, x: 0, y: 12)
    }

    private var footerBlock: some View {
        HStack(alignment: .center, spacing: 20) {
            VStack(alignment: .leading, spacing: 6) {
                Text("Powered by MealMood")
                    .font(.system(size: 30, weight: .bold, design: .rounded))
                    .foregroundColor(Color(hex: "#3A3A3A"))
                Text(shareURL)
                    .font(.system(size: 24, weight: .semibold, design: .rounded))
                    .foregroundColor(Color(hex: "#588A77"))
            }

            Spacer()

            if let qrImage {
                VStack(spacing: 6) {
                    Image(uiImage: qrImage)
                        .interpolation(.none)
                        .resizable()
                        .scaledToFit()
                        .frame(width: 162, height: 162)
                        .padding(10)
                        .background(Color.white)
                        .clipShape(RoundedRectangle(cornerRadius: 18))
                    Text("Scan me")
                        .font(.system(size: 18, weight: .semibold, design: .rounded))
                        .foregroundColor(.mealMoodTextSecondary)
                }
            }
        }
        .padding(.horizontal, 26)
        .padding(.vertical, 18)
        .background(Color.white.opacity(0.8))
        .clipShape(RoundedRectangle(cornerRadius: 22))
        .overlay(
            RoundedRectangle(cornerRadius: 22)
                .stroke(Color(hex: "#DDEEE6"), lineWidth: 1)
        )
        .shadow(color: Color(hex: "#7F9E90").opacity(0.14), radius: 16, x: 0, y: 8)
    }

    private func gridHeaderCell(_ title: String, day: Int?) -> some View {
        let background = dayHeaderBackground(day: day)
        return Text(title)
            .font(.system(size: 25, weight: .bold, design: .rounded))
            .foregroundColor(.mealMoodTextPrimary)
            .frame(maxWidth: .infinity, minHeight: 92)
            .padding(.horizontal, 10)
            .background(background)
            .clipShape(RoundedRectangle(cornerRadius: 14))
            .overlay(
                RoundedRectangle(cornerRadius: 14)
                    .stroke(Color.white.opacity(0.6), lineWidth: 1)
            )
    }

    private func gridMealCell(_ title: String, icon: String, mealType: MealType) -> some View {
        let background = mealType == .lunch ?
            LinearGradient(colors: [Color(hex: "#FFE2C8"), Color(hex: "#FFD4B2")], startPoint: .topLeading, endPoint: .bottomTrailing) :
            LinearGradient(colors: [Color(hex: "#D7EFE7"), Color(hex: "#C2E7DB")], startPoint: .topLeading, endPoint: .bottomTrailing)
        return HStack(spacing: 8) {
            Image(systemName: icon)
            Text(title)
        }
        .font(.system(size: 25, weight: .bold, design: .rounded))
        .foregroundColor(Color(hex: "#365548"))
        .frame(maxWidth: .infinity, minHeight: 130)
        .padding(.horizontal, 14)
        .background(background)
        .clipShape(RoundedRectangle(cornerRadius: 14))
        .overlay(
            RoundedRectangle(cornerRadius: 14)
                .stroke(Color.white.opacity(0.6), lineWidth: 1)
        )
    }

    private func gridDishCell(_ title: String, day: Int) -> some View {
        let tint = dayCellTint(day: day)
        return Text(title)
            .font(.system(size: 26, weight: .medium))
            .foregroundColor(.mealMoodTextPrimary)
            .multilineTextAlignment(.center)
            .lineLimit(3)
            .minimumScaleFactor(0.6)
            .frame(maxWidth: .infinity, minHeight: 130)
            .padding(.horizontal, 10)
            .background(
                LinearGradient(
                    colors: [Color.white.opacity(0.95), tint.opacity(0.32)],
                    startPoint: .topLeading,
                    endPoint: .bottomTrailing
                )
            )
            .clipShape(RoundedRectangle(cornerRadius: 14))
            .overlay(
                RoundedRectangle(cornerRadius: 14)
                    .stroke(Color(hex: "#F2E5DE"), lineWidth: 1)
            )
    }

    private func dayHeaderBackground(day: Int?) -> LinearGradient {
        guard let day else {
            return LinearGradient(
                colors: [Color(hex: "#F6E7DE"), Color(hex: "#F2DED2")],
                startPoint: .topLeading,
                endPoint: .bottomTrailing
            )
        }
        let palettes: [(String, String)] = [
            ("#FFD5D9", "#FFC8D2"),
            ("#FFE1C8", "#FFD3AF"),
            ("#FFF0C8", "#FFE6A8"),
            ("#DFF2CC", "#CFEAB6"),
            ("#D3F0E7", "#BFE6DA"),
            ("#D9E8FF", "#C9DDFF"),
            ("#E6D9FF", "#D9C8FF")
        ]
        let index = max(0, min(day, palettes.count - 1))
        return LinearGradient(
            colors: [Color(hex: palettes[index].0), Color(hex: palettes[index].1)],
            startPoint: .topLeading,
            endPoint: .bottomTrailing
        )
    }

    private func dayCellTint(day: Int) -> Color {
        let colors = [
            Color(hex: "#FFD0D8"),
            Color(hex: "#FFE1C6"),
            Color(hex: "#FFF0C3"),
            Color(hex: "#DFF1CA"),
            Color(hex: "#D5EFE6"),
            Color(hex: "#D7E7FF"),
            Color(hex: "#E7DCFF")
        ]
        return colors[max(0, min(day, colors.count - 1))]
    }
}
