package com.example.sleeptracker;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import org.json.JSONArray;
import org.json.JSONObject;

import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

public class MainActivity extends AppCompatActivity {

    private static final long HOLD_MS = 1500;
    private static final String PREFS = "sleep_prefs";

    private View loginScreen, mainScreen;
    private EditText inputUsername, inputPassword;
    private TextView loginError;
    private TextView statusIcon, statusLabel, statusTime;
    private FrameLayout btnBed, btnSleep, btnLazy, btnWake;
    private View fillBed, fillSleep, fillLazy, fillWake;
    private LinearLayout historyContainer;

    private SleepApi api;
    private ValueAnimator currentAnim;

    private static final Map<String, String> KEY_ICONS = new HashMap<>();
    private static final Map<String, Integer> KEY_COLORS = new HashMap<>();
    private static final Map<String, String> KEY_LABELS = new HashMap<>();

    static {
        KEY_ICONS.put("wake", "☀️");
        KEY_ICONS.put("bed", "🛌");
        KEY_ICONS.put("sleep", "💤");
        KEY_ICONS.put("lazy", "😴");

        KEY_COLORS.put("wake", 0xFFFFFFFF);
        KEY_COLORS.put("bed", 0xFF27AE60);
        KEY_COLORS.put("sleep", 0xFF8E44AD);
        KEY_COLORS.put("lazy", 0xFF27AE60);

        KEY_LABELS.put("wake", "清醒");
        KEY_LABELS.put("bed", "躺床");
        KEY_LABELS.put("sleep", "睡眠");
        KEY_LABELS.put("lazy", "賴床");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        api = new SleepApi();

        loginScreen = findViewById(R.id.loginScreen);
        mainScreen = findViewById(R.id.mainScreen);
        inputUsername = findViewById(R.id.inputUsername);
        inputPassword = findViewById(R.id.inputPassword);
        loginError = findViewById(R.id.loginError);

        statusIcon = findViewById(R.id.statusIcon);
        statusLabel = findViewById(R.id.statusLabel);
        statusTime = findViewById(R.id.statusTime);

        btnBed = findViewById(R.id.btnBed);
        btnSleep = findViewById(R.id.btnSleep);
        btnLazy = findViewById(R.id.btnLazy);
        btnWake = findViewById(R.id.btnWake);

        fillBed = findViewById(R.id.fillBed);
        fillSleep = findViewById(R.id.fillSleep);
        fillLazy = findViewById(R.id.fillLazy);
        fillWake = findViewById(R.id.fillWake);

        historyContainer = findViewById(R.id.historyContainer);

        setupHoldButton(btnBed, fillBed, "bed");
        setupHoldButton(btnSleep, fillSleep, "sleep");
        setupHoldButton(btnLazy, fillLazy, "lazy");
        setupHoldButton(btnWake, fillWake, "wake");

        findViewById(R.id.btnLogin).setOnClickListener(v -> doLogin());
        findViewById(R.id.btnLogout).setOnClickListener(v -> doLogout());

        SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
        String savedUser = prefs.getString("username", null);
        String savedPass = prefs.getString("password", null);

        if (savedUser != null && savedPass != null) {
            api.setCredentials(savedUser, savedPass);
            showMain();
        } else {
            showLogin();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mainScreen.getVisibility() == View.VISIBLE) {
            loadData();
        }
    }

    private void showLogin() {
        loginScreen.setVisibility(View.VISIBLE);
        mainScreen.setVisibility(View.GONE);
        loginError.setVisibility(View.GONE);
        inputUsername.setText("");
        inputPassword.setText("");
    }

    private void showMain() {
        loginScreen.setVisibility(View.GONE);
        mainScreen.setVisibility(View.VISIBLE);
        loadData();
    }

    private void doLogin() {
        String user = inputUsername.getText().toString().trim();
        String pass = inputPassword.getText().toString();

        if (user.isEmpty() || pass.isEmpty()) {
            loginError.setText("請輸入帳號和密碼");
            loginError.setVisibility(View.VISIBLE);
            return;
        }

        loginError.setVisibility(View.GONE);
        findViewById(R.id.btnLogin).setEnabled(false);

        api.setCredentials(user, pass);
        api.getStatus(new SleepApi.StatusCallback() {
            @Override
            public void onResult(String action, String actionKey, String recordedAt) {
                if (isFinishing()) return;
                findViewById(R.id.btnLogin).setEnabled(true);
                getSharedPreferences(PREFS, MODE_PRIVATE).edit()
                        .putString("username", user)
                        .putString("password", pass)
                        .apply();
                showMain();
            }

            @Override
            public void onError(String error, boolean authFailed) {
                if (isFinishing()) return;
                findViewById(R.id.btnLogin).setEnabled(true);
                loginError.setText(authFailed ? "帳號或密碼錯誤" : "連線失敗：" + error);
                loginError.setVisibility(View.VISIBLE);
            }
        });
    }

    private void doLogout() {
        getSharedPreferences(PREFS, MODE_PRIVATE).edit().clear().apply();
        api.setCredentials(null, null);
        showLogin();
    }

    private void onAuthFailed() {
        getSharedPreferences(PREFS, MODE_PRIVATE).edit().clear().apply();
        Toast.makeText(this, "登入已過期，請重新登入", Toast.LENGTH_SHORT).show();
        showLogin();
    }

    private void loadData() {
        api.getStatus(new SleepApi.StatusCallback() {
            @Override
            public void onResult(String action, String actionKey, String recordedAt) {
                if (isFinishing()) return;
                updateStatusUI(actionKey, recordedAt);
                updateButtons(actionKey);
            }

            @Override
            public void onError(String error, boolean authFailed) {
                if (isFinishing()) return;
                if (authFailed) { onAuthFailed(); return; }
                statusLabel.setText("連線失敗");
                statusTime.setVisibility(View.VISIBLE);
                statusTime.setText(error);
            }
        });

        api.getHistory(10, new SleepApi.HistoryCallback() {
            @Override
            public void onResult(JSONArray records) {
                if (isFinishing()) return;
                updateHistory(records);
            }

            @Override
            public void onError(String error, boolean authFailed) {
            }
        });
    }

    private void updateStatusUI(String actionKey, String recordedAt) {
        if (actionKey == null || actionKey.isEmpty()) {
            statusIcon.setText("☀️");
            statusLabel.setText("目前狀態：無紀錄");
            statusLabel.setTextColor(0xFFFFFFFF);
            statusTime.setVisibility(View.GONE);
            return;
        }

        String label = KEY_LABELS.getOrDefault(actionKey, actionKey);
        statusIcon.setText(KEY_ICONS.getOrDefault(actionKey, "☀️"));
        statusLabel.setText("目前狀態：" + label);
        statusLabel.setTextColor(KEY_COLORS.getOrDefault(actionKey, 0xFFFFFFFF));

        if (recordedAt != null && recordedAt.length() >= 15) {
            statusTime.setText("自 " + formatTime(recordedAt) + "（" + calcElapsed(recordedAt) + "）");
            statusTime.setVisibility(View.VISIBLE);
        } else {
            statusTime.setVisibility(View.GONE);
        }
    }

    private void updateButtons(String actionKey) {
        boolean bed = false, sleep = false, lazy = false, wake = false;

        if (actionKey == null || actionKey.isEmpty()) {
            bed = true; sleep = true;
        } else switch (actionKey) {
            case "wake": bed = true; sleep = true; break;
            case "bed":  sleep = true; wake = true; break;
            case "sleep": lazy = true; wake = true; break;
            case "lazy": sleep = true; wake = true; break;
            default: bed = true; sleep = true; break;
        }

        btnBed.setVisibility(bed ? View.VISIBLE : View.GONE);
        btnSleep.setVisibility(sleep ? View.VISIBLE : View.GONE);
        btnLazy.setVisibility(lazy ? View.VISIBLE : View.GONE);
        btnWake.setVisibility(wake ? View.VISIBLE : View.GONE);
    }

    @SuppressWarnings("ClickableViewAccessibility")
    private void setupHoldButton(FrameLayout btn, View fillView, String actionType) {
        btn.setOnTouchListener((v, event) -> {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    cancelAnim();
                    v.getParent().requestDisallowInterceptTouchEvent(true);

                    ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
                    anim.setDuration(HOLD_MS);
                    anim.setInterpolator(new LinearInterpolator());
                    anim.addUpdateListener(animation -> {
                        float fraction = (float) animation.getAnimatedValue();
                        ViewGroup.LayoutParams lp = fillView.getLayoutParams();
                        lp.width = (int) (btn.getWidth() * fraction);
                        fillView.setLayoutParams(lp);
                    });
                    anim.addListener(new AnimatorListenerAdapter() {
                        private boolean cancelled = false;
                        @Override
                        public void onAnimationCancel(Animator animation) { cancelled = true; }
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            resetFill(fillView);
                            if (!cancelled) performCheckin(actionType);
                        }
                    });
                    currentAnim = anim;
                    anim.start();
                    return true;

                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    v.getParent().requestDisallowInterceptTouchEvent(false);
                    cancelAnim();
                    resetFill(fillView);
                    return true;
            }
            return false;
        });
    }

    private void cancelAnim() {
        if (currentAnim != null && currentAnim.isRunning()) currentAnim.cancel();
        currentAnim = null;
    }

    private void resetFill(View fillView) {
        ViewGroup.LayoutParams lp = fillView.getLayoutParams();
        lp.width = 0;
        fillView.setLayoutParams(lp);
    }

    private void performCheckin(String type) {
        Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
        if (vibrator != null && vibrator.hasVibrator()) {
            vibrator.vibrate(VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE));
        }

        setButtonsEnabled(false);

        api.checkin(type, new SleepApi.CheckinCallback() {
            @Override
            public void onResult(int id, String recordedAt, String action) {
                if (isFinishing()) return;
                String label = action != null ? action : type;
                Toast.makeText(MainActivity.this, label + " ✓", Toast.LENGTH_SHORT).show();
                setButtonsEnabled(true);
                loadData();
            }

            @Override
            public void onError(String error, boolean authFailed) {
                if (isFinishing()) return;
                if (authFailed) { onAuthFailed(); return; }
                Toast.makeText(MainActivity.this, "打卡失敗：" + error, Toast.LENGTH_LONG).show();
                setButtonsEnabled(true);
            }
        });
    }

    private void setButtonsEnabled(boolean enabled) {
        float alpha = enabled ? 1f : 0.5f;
        for (FrameLayout btn : new FrameLayout[]{btnBed, btnSleep, btnLazy, btnWake}) {
            btn.setEnabled(enabled);
            btn.setAlpha(alpha);
        }
    }

    private void updateHistory(JSONArray records) {
        historyContainer.removeAllViews();
        int len = records.length();
        if (len == 0) {
            TextView empty = new TextView(this);
            empty.setText("尚無紀錄");
            empty.setTextColor(0xFF888888);
            empty.setTextSize(14);
            historyContainer.addView(empty);
            return;
        }
        for (int i = 0; i < len; i++) {
            try {
                JSONObject rec = records.getJSONObject(i);
                String recordedAt = rec.getString("recorded_at");
                String action = rec.getString("action");

                LinearLayout row = new LinearLayout(this);
                row.setOrientation(LinearLayout.HORIZONTAL);
                int pad = dpToPx(8);
                row.setPadding(0, pad, 0, pad);

                TextView timeView = new TextView(this);
                timeView.setText(formatTime(recordedAt));
                timeView.setTextColor(0xFF888888);
                timeView.setTextSize(14);
                timeView.setLayoutParams(new LinearLayout.LayoutParams(
                        0, ViewGroup.LayoutParams.WRAP_CONTENT, 1));

                TextView actionView = new TextView(this);
                actionView.setText(action);
                int color = 0xFFFFFFFF;
                for (Map.Entry<String, String> e : KEY_LABELS.entrySet()) {
                    if (e.getValue().equals(action)) {
                        color = KEY_COLORS.getOrDefault(e.getKey(), 0xFFFFFFFF);
                        break;
                    }
                }
                actionView.setTextColor(color);
                actionView.setTextSize(14);
                actionView.setGravity(Gravity.END);

                row.addView(timeView);
                row.addView(actionView);
                historyContainer.addView(row);

                if (i < len - 1) {
                    View divider = new View(this);
                    divider.setBackgroundColor(0xFF333333);
                    divider.setLayoutParams(new LinearLayout.LayoutParams(
                            ViewGroup.LayoutParams.MATCH_PARENT, 1));
                    historyContainer.addView(divider);
                }
            } catch (Exception ignored) {
            }
        }
    }

    private String formatTime(String dt) {
        if (dt == null || dt.length() < 15) return dt != null ? dt : "";
        return dt.substring(4, 6) + "/" + dt.substring(6, 8) + " "
                + dt.substring(9, 11) + ":" + dt.substring(11, 13);
    }

    private String calcElapsed(String dt) {
        if (dt == null || dt.length() < 15) return "";
        try {
            Calendar cal = Calendar.getInstance();
            cal.set(Integer.parseInt(dt.substring(0, 4)),
                    Integer.parseInt(dt.substring(4, 6)) - 1,
                    Integer.parseInt(dt.substring(6, 8)),
                    Integer.parseInt(dt.substring(9, 11)),
                    Integer.parseInt(dt.substring(11, 13)),
                    Integer.parseInt(dt.substring(13, 15)));
            cal.set(Calendar.MILLISECOND, 0);
            long diff = (System.currentTimeMillis() - cal.getTimeInMillis()) / 1000;
            if (diff < 0) diff = 0;
            if (diff < 60) return "剛剛";
            if (diff < 3600) return (diff / 60) + " 分鐘前";
            return (diff / 3600) + " 小時 " + ((diff % 3600) / 60) + " 分鐘前";
        } catch (Exception e) {
            return "";
        }
    }

    private int dpToPx(int dp) {
        return (int) (dp * getResources().getDisplayMetrics().density);
    }
}
