package de.winniepat.citrus.gui;

import icyllis.modernui.core.Context;
import icyllis.modernui.fragment.Fragment;
import icyllis.modernui.graphics.Canvas;
import icyllis.modernui.graphics.Paint;
import icyllis.modernui.graphics.drawable.ShapeDrawable;
import icyllis.modernui.mc.ScreenCallback;
import icyllis.modernui.util.DataSet;
import icyllis.modernui.view.*;
import icyllis.modernui.widget.*;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.ingame.InventoryScreen;
import net.minecraft.entity.LivingEntity;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * Test screen that renders a spinnable player preview with all cosmetics
 * (capes, wings, halos, and hats).
 *
 * The player entity is rendered with all cosmetics automatically because
 * the cosmetic feature renderers (WingsFeatureRenderer, HatFeatureRenderer,
 * HaloFeatureRenderer) are already registered and will render on any player
 * entity rendering. Capes are handled via the SkinTextures modification.
 */
public class TestScreen extends Fragment implements ScreenCallback {

    private static TestScreen activeInstance = null;

    private float mPlayerRotationY = 0f;
    private float mPlayerRotationX = 0f;
    private float mLastTouchX = 0f;
    private float mLastTouchY = 0f;
    private boolean mIsDragging = false;
    private boolean mAutoSpinning = false;
    private PlayerPreviewView mPlayerPreview;

    // Store the preview bounds for Minecraft rendering
    private int mPreviewCenterX = 0;
    private int mPreviewCenterY = 0;
    private int mPreviewSize = 80;
    private boolean mPreviewBoundsSet = false;

    @Override
    public void onCreate(@Nullable DataSet savedInstanceState) {
        super.onCreate(savedInstanceState);
        activeInstance = this;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (activeInstance == this) {
            activeInstance = null;
            mPreviewBoundsSet = false;
        }
    }

    @Override
    public View onCreateView(@NotNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable DataSet savedInstanceState) {
        Context context = requireContext();

        FrameLayout root = new FrameLayout(context);
        root.setLayoutParams(new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT
        ));

        // Semi-transparent background
        ShapeDrawable backgroundDrawable = new ShapeDrawable();
        backgroundDrawable.setShape(ShapeDrawable.RECTANGLE);
        backgroundDrawable.setColor(0x80000000);
        root.setBackground(backgroundDrawable);

        // Main content container
        LinearLayout contentContainer = new LinearLayout(context);
        contentContainer.setOrientation(LinearLayout.VERTICAL);
        contentContainer.setGravity(Gravity.CENTER);
        FrameLayout.LayoutParams contentParams = new FrameLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT
        );
        contentContainer.setLayoutParams(contentParams);

        // Title
        TextView title = new TextView(context);
        title.setText("Player Preview");
        title.setTextSize(28);
        title.setTextColor(0xFFFFFFFF);
        title.setGravity(Gravity.CENTER);
        LinearLayout.LayoutParams titleParams = new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT
        );
        titleParams.setMargins(0, dp(20), 0, dp(10));
        title.setLayoutParams(titleParams);
        contentContainer.addView(title);

        // Subtitle
        TextView subtitle = new TextView(context);
        subtitle.setText("Drag to rotate the player - Shows capes, wings, halos & hats");
        subtitle.setTextSize(14);
        subtitle.setTextColor(0xAAFFFFFF);
        subtitle.setGravity(Gravity.CENTER);
        LinearLayout.LayoutParams subtitleParams = new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT
        );
        subtitleParams.setMargins(0, 0, 0, dp(20));
        subtitle.setLayoutParams(subtitleParams);
        contentContainer.addView(subtitle);

        // Player preview container with border
        FrameLayout previewContainer = new FrameLayout(context);
        ShapeDrawable previewBackground = new ShapeDrawable();
        previewBackground.setShape(ShapeDrawable.RECTANGLE);
        previewBackground.setColor(0x40000000);
        previewBackground.setCornerRadius(dp(10));
        previewBackground.setStroke(dp(2), 0x60FFFFFF);
        previewContainer.setBackground(previewBackground);

        LinearLayout.LayoutParams previewContainerParams = new LinearLayout.LayoutParams(
                dp(300),
                dp(400)
        );
        previewContainerParams.gravity = Gravity.CENTER;
        previewContainer.setLayoutParams(previewContainerParams);

        // Custom player preview view
        mPlayerPreview = new PlayerPreviewView(context);
        mPlayerPreview.setLayoutParams(new FrameLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT
        ));
        previewContainer.addView(mPlayerPreview);

        contentContainer.addView(previewContainer);

        // Buttons container
        LinearLayout buttonsContainer = new LinearLayout(context);
        buttonsContainer.setOrientation(LinearLayout.HORIZONTAL);
        buttonsContainer.setGravity(Gravity.CENTER);
        LinearLayout.LayoutParams buttonsParams = new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT
        );
        buttonsParams.setMargins(0, dp(20), 0, 0);
        buttonsContainer.setLayoutParams(buttonsParams);

        // Reset rotation button
        Button resetButton = new Button(context);
        resetButton.setText("Reset Rotation");
        resetButton.setTextSize(14);
        ShapeDrawable buttonBackground = new ShapeDrawable();
        buttonBackground.setShape(ShapeDrawable.RECTANGLE);
        buttonBackground.setColor(0x80FFFFFF);
        buttonBackground.setCornerRadius(dp(5));
        resetButton.setBackground(buttonBackground);
        resetButton.setOnClickListener(v -> {
            mPlayerRotationY = 0f;
            mPlayerRotationX = 0f;
        });
        LinearLayout.LayoutParams resetParams = new LinearLayout.LayoutParams(
                dp(150),
                dp(40)
        );
        resetParams.setMargins(0, 0, dp(10), 0);
        resetButton.setLayoutParams(resetParams);
        buttonsContainer.addView(resetButton);

        // Spin button (auto-rotate)
        Button spinButton = new Button(context);
        spinButton.setText("Auto Spin");
        spinButton.setTextSize(14);
        ShapeDrawable spinBackground = new ShapeDrawable();
        spinBackground.setShape(ShapeDrawable.RECTANGLE);
        spinBackground.setColor(0x8055AAFF);
        spinBackground.setCornerRadius(dp(5));
        spinButton.setBackground(spinBackground);
        spinButton.setOnClickListener(v -> {
            mAutoSpinning = !mAutoSpinning;
            spinButton.setText(mAutoSpinning ? "Stop Spin" : "Auto Spin");
            if (mAutoSpinning) {
                startAutoSpin();
            }
        });
        LinearLayout.LayoutParams spinParams = new LinearLayout.LayoutParams(
                dp(150),
                dp(40)
        );
        spinParams.setMargins(dp(10), 0, 0, 0);
        spinButton.setLayoutParams(spinParams);
        buttonsContainer.addView(spinButton);

        contentContainer.addView(buttonsContainer);

        // Close button
        Button closeButton = new Button(context);
        closeButton.setText("Close");
        closeButton.setTextSize(14);
        ShapeDrawable closeBackground = new ShapeDrawable();
        closeBackground.setShape(ShapeDrawable.RECTANGLE);
        closeBackground.setColor(0x80FF5555);
        closeBackground.setCornerRadius(dp(5));
        closeButton.setBackground(closeBackground);
        closeButton.setOnClickListener(v ->
            MinecraftClient.getInstance().execute(() ->
                MinecraftClient.getInstance().setScreen(null)
            )
        );
        LinearLayout.LayoutParams closeParams = new LinearLayout.LayoutParams(
                dp(150),
                dp(40)
        );
        closeParams.gravity = Gravity.CENTER;
        closeParams.setMargins(0, dp(10), 0, dp(20));
        closeButton.setLayoutParams(closeParams);
        contentContainer.addView(closeButton);

        root.addView(contentContainer);

        return root;
    }

    private void startAutoSpin() {
        if (mPlayerPreview != null) {
            mPlayerPreview.post(new Runnable() {
                @Override
                public void run() {
                    if (activeInstance == TestScreen.this && mAutoSpinning) {
                        mPlayerRotationY += 2f;
                        if (mPlayerRotationY > 360f) mPlayerRotationY -= 360f;
                        mPlayerPreview.postDelayed(this, 16); // ~60 FPS
                    }
                }
            });
        }
    }

    /**
     * Custom view that renders the player entity with cosmetics.
     * Handles touch events for rotation.
     */
    private class PlayerPreviewView extends View {

        public PlayerPreviewView(Context context) {
            super(context);
        }

        @Override
        public boolean onTouchEvent(@NotNull MotionEvent event) {
            float x = event.getX();
            float y = event.getY();

            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    mIsDragging = true;
                    mLastTouchX = x;
                    mLastTouchY = y;
                    return true;

                case MotionEvent.ACTION_MOVE:
                    if (mIsDragging) {
                        float deltaX = x - mLastTouchX;
                        float deltaY = y - mLastTouchY;

                        // Horizontal drag rotates around Y axis
                        mPlayerRotationY += deltaX * 0.5f;

                        // Vertical drag rotates around X axis (limited range)
                        mPlayerRotationX += deltaY * 0.3f;
                        mPlayerRotationX = Math.max(-30f, Math.min(30f, mPlayerRotationX));

                        mLastTouchX = x;
                        mLastTouchY = y;
                        invalidate();
                    }
                    return true;

                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    mIsDragging = false;
                    return true;
            }

            return super.onTouchEvent(event);
        }

        @Override
        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
            super.onLayout(changed, left, top, right, bottom);

            // Calculate the center position in screen coordinates for Minecraft rendering
            int[] location = new int[2];
            getLocationOnScreen(location);

            MinecraftClient client = MinecraftClient.getInstance();
            float guiScale = (float) client.getWindow().getScaleFactor();

            // Convert ModernUI coordinates to Minecraft screen coordinates
            int viewWidth = right - left;
            int viewHeight = bottom - top;

            // Calculate position - the location is in window pixels, need to convert to scaled GUI coordinates
            mPreviewCenterX = (int) ((location[0] + viewWidth / 2.0f) / guiScale);
            mPreviewCenterY = (int) ((location[1] + viewHeight * 0.7f) / guiScale);
            mPreviewSize = (int) (Math.min(viewWidth, viewHeight) / guiScale / 2.5f);
            mPreviewBoundsSet = true;

            System.out.println("[TestScreen] Layout: location=" + location[0] + "," + location[1] +
                " size=" + viewWidth + "x" + viewHeight +
                " guiScale=" + guiScale +
                " preview: center=" + mPreviewCenterX + "," + mPreviewCenterY + " size=" + mPreviewSize);
        }

        @Override
        protected void onDraw(@NotNull Canvas canvas) {
            super.onDraw(canvas);

            // Draw background
            Paint paint = Paint.obtain();
            paint.setColor(0x15FFFFFF);
            canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
            paint.recycle();

            // Keep redrawing for smooth updates
            MinecraftClient client = MinecraftClient.getInstance();
            if (client.player != null) {
                postInvalidateDelayed(16);
            }
        }
    }

    /**
     * Renders the player entity at the specified position with rotation.
     * This method renders the player with all cosmetics (capes, wings, halos, hats)
     * because the cosmetic feature renderers are already registered in the game.
     */
    public static void renderPlayerEntity(DrawContext context, int x, int y, int size,
                                         float rotationX, float rotationY, LivingEntity entity) {
        if (entity == null) return;

        // Save original rotation values
        float originalBodyYaw = entity.bodyYaw;
        float originalYaw = entity.getYaw();
        float originalPitch = entity.getPitch();
        float originalPrevHeadYaw = entity.prevHeadYaw;
        float originalHeadYaw = entity.headYaw;

        // Set rotation based on user input
        entity.bodyYaw = 180.0F + rotationY;
        entity.setYaw(180.0F + rotationY);
        entity.setPitch(-rotationX);
        entity.headYaw = entity.getYaw();
        entity.prevHeadYaw = entity.getYaw();

        // Calculate scale based on entity height
        float entityScale = entity.getHeight() > 2.0F ? 2.0F / entity.getHeight() : 1.0F;

        // Use InventoryScreen's drawEntity method for proper rendering
        // This will automatically render all cosmetics (capes, wings, halos, hats)
        // because the feature renderers are registered globally
        InventoryScreen.drawEntity(
                context,
                x - size / 2,
                y - size,
                x + size / 2,
                y + size / 4,
                (int) (size * 0.8f * entityScale),
                0.0625F,
                0, 0,  // mouseX, mouseY - not following mouse
                entity
        );

        // Restore original rotation values
        entity.bodyYaw = originalBodyYaw;
        entity.setYaw(originalYaw);
        entity.setPitch(originalPitch);
        entity.prevHeadYaw = originalPrevHeadYaw;
        entity.headYaw = originalHeadYaw;
    }

    /**
     * Get the current active TestScreen instance.
     * Used by the render callback to access rotation values.
     */
    public static TestScreen getActiveInstance() {
        return activeInstance;
    }

    public float getPlayerRotationY() {
        return mPlayerRotationY;
    }

    public float getPlayerRotationX() {
        return mPlayerRotationX;
    }

    public int getPreviewCenterX() {
        return mPreviewCenterX;
    }

    public int getPreviewCenterY() {
        return mPreviewCenterY;
    }

    public int getPreviewSize() {
        return mPreviewSize;
    }

    public boolean isPreviewBoundsSet() {
        return mPreviewBoundsSet;
    }

    private int dp(int value) {
        Context ctx = getContext();
        if (ctx == null) return value;
        return (int) (value * ctx.getResources().getDisplayMetrics().density);
    }

    @Override
    public boolean isPauseScreen() {
        return false;
    }

    @Override
    public boolean shouldBlurBackground() {
        return true;
    }

    @Override
    public boolean hasDefaultBackground() {
        return false;
    }

    /**
     * Initialize the render callback for player preview rendering.
     * Note: Rendering is now handled by ScreenRenderMixin.
     * This method is kept for backward compatibility.
     */
    public static void registerRenderer() {
        // Rendering is now handled by ScreenRenderMixin
        // This method is kept for backward compatibility
    }
}
