from flask import Flask, render_template, request, jsonify, session
import subprocess, json, os, sys, tempfile

app = Flask(__name__)
app.secret_key = 'pyshikhi_secret_2024_ebaubrcc'

LESSONS = [
    {"id":1,"title":"পাইথন পরিচিতি","title_en":"Introduction to Python","category":"basic","icon":"🐍","description":"পাইথন কী এবং কেন শিখব — প্রথম প্রোগ্রাম লেখা","explanation":"<h3>পাইথন কী?</h3><p>পাইথন একটি সহজ, শক্তিশালী প্রোগ্রামিং ভাষা। <code>print()</code> দিয়ে স্ক্রিনে কিছু দেখানো যায়।</p><h3>উদাহরণ</h3><pre><code>print('হ্যালো বাংলাদেশ!')</code></pre><h3>মন্তব্য</h3><pre><code># এটি একটি মন্তব্য\nprint('পাইথন মজার!')</code></pre>","starter_code":"# আমার প্রথম পাইথন প্রোগ্রাম\nprint('হ্যালো, বাংলাদেশ!')\nprint('পাইথন শেখা শুরু করলাম!')\n","challenge":"আপনার নিজের নাম এবং জেলার নাম প্রিন্ট করুন।","expected_hint":"print() দিয়ে আপনার নাম লিখুন"},
    {"id":2,"title":"ভেরিয়েবল ও ডেটা টাইপ","title_en":"Variables & Data Types","category":"basic","icon":"📦","description":"ভেরিয়েবলে ডেটা সংরক্ষণ এবং বিভিন্ন ডেটা টাইপ","explanation":"<h3>ভেরিয়েবল</h3><p>ভেরিয়েবল হলো একটি বাক্স যেখানে ডেটা রাখি।</p><pre><code>নাম = 'রহিম'\nবয়স = 20\nউচ্চতা = 5.6</code></pre><h3>ডেটা টাইপ</h3><pre><code>x = 10      # int\ny = 3.14    # float\nz = 'বাংলা' # str\nb = True    # bool\nprint(type(x))</code></pre>","starter_code":"নাম = 'আপনার নাম'\nবয়স = 25\nশহর = 'ঢাকা'\nprint('নাম:', নাম)\nprint('বয়স:', বয়স)\nprint('শহর:', শহর)\nprint('টাইপ:', type(বয়স))\n","challenge":"আপনার নাম, বয়স, জেলা ও CGPA ভেরিয়েবল বানিয়ে প্রিন্ট করুন।","expected_hint":"float দিয়ে CGPA রাখুন"},
    {"id":3,"title":"ইনপুট ও আউটপুট","title_en":"Input & Output","category":"basic","icon":"⌨️","description":"ব্যবহারকারীর কাছ থেকে ডেটা নেওয়া","explanation":"<h3>input() ফাংশন</h3><pre><code>নাম = input('আপনার নাম: ')\nprint('স্বাগতম,', নাম)</code></pre><h3>সংখ্যা ইনপুট</h3><pre><code>বয়স = int(input('বয়স: '))\nউচ্চতা = float(input('উচ্চতা: '))</code></pre><h3>f-string</h3><pre><code>print(f'আমার নাম {নাম}, বয়স {বয়স}')</code></pre>","starter_code":"নাম = input('আপনার নাম: ')\nবয়স = int(input('আপনার বয়স: '))\nprint(f'স্বাগতম {নাম}!')\nprint(f'আগামী বছর আপনার বয়স {বয়স+1}')\n","challenge":"দুটি সংখ্যা নিয়ে যোগ, বিয়োগ, গুণ, ভাগ দেখান।","expected_hint":"int(input()) দিয়ে সংখ্যা নিন"},
    {"id":4,"title":"শর্ত (if-elif-else)","title_en":"Conditions","category":"basic","icon":"🔀","description":"শর্তের উপর ভিত্তি করে সিদ্ধান্ত নেওয়া","explanation":"<h3>if-else</h3><pre><code>বয়স = 18\nif বয়স >= 18:\n    print('ভোটার')\nelse:\n    print('ভোটার নন')</code></pre><h3>elif</h3><pre><code>নম্বর = 75\nif নম্বর >= 80:\n    print('A')\nelif নম্বর >= 60:\n    print('B')\nelse:\n    print('F')</code></pre>","starter_code":"নম্বর = int(input('নম্বর দিন: '))\nif নম্বর >= 80:\n    print('A+ — চমৎকার!')\nelif নম্বর >= 70:\n    print('A — খুব ভালো!')\nelif নম্বর >= 60:\n    print('B — ভালো')\nelif নম্বর >= 50:\n    print('C — মোটামুটি')\nelse:\n    print('F — আরো পড়ুন')\n","challenge":"BMI ক্যালকুলেটর: ওজন ও উচ্চতা নিয়ে Underweight/Normal/Overweight বলুন।","expected_hint":"BMI = ওজন / (উচ্চতা ** 2)"},
    {"id":5,"title":"লুপ (for ও while)","title_en":"Loops","category":"basic","icon":"🔄","description":"একই কাজ বারবার করানো","explanation":"<h3>for লুপ</h3><pre><code>for i in range(5):\n    print(i)</code></pre><h3>while লুপ</h3><pre><code>i = 0\nwhile i < 5:\n    print(i)\n    i += 1</code></pre><h3>লিস্টে লুপ</h3><pre><code>ফল = ['আম','কলা','লিচু']\nfor f in ফল:\n    print(f)</code></pre>","starter_code":"সংখ্যা = int(input('নামতা কোনটির? '))\nfor i in range(1, 11):\n    print(f'{সংখ্যা} x {i} = {সংখ্যা*i}')\n","challenge":"১ থেকে ৫০ পর্যন্ত বিজোড় সংখ্যা প্রিন্ট করুন ও যোগফল বলুন।","expected_hint":"i % 2 != 0 দিয়ে বিজোড় চেক করুন"},
    {"id":6,"title":"ফাংশন","title_en":"Functions","category":"intermediate","icon":"⚙️","description":"কোড পুনরায় ব্যবহারের জন্য ফাংশন","explanation":"<h3>ফাংশন তৈরি</h3><pre><code>def স্বাগতম(নাম):\n    print(f'স্বাগতম {নাম}!')\nস্বাগতম('রহিম')</code></pre><h3>return</h3><pre><code>def যোগ(ক, খ):\n    return ক + খ\nফল = যোগ(10, 20)\nprint(ফল)</code></pre><h3>ডিফল্ট মান</h3><pre><code>def অভিনন্দন(নাম, ভাষা='বাংলা'):\n    print(f'{নাম} {ভাষা} শিখছেন')</code></pre>","starter_code":"def ক্যালকুলেটর(ক, খ, অপ):\n    if অপ == '+':\n        return ক + খ\n    elif অপ == '-':\n        return ক - খ\n    elif অপ == '*':\n        return ক * খ\n    elif অপ == '/':\n        return ক / খ if খ != 0 else 'ভুল'\n\nprint(ক্যালকুলেটর(10, 5, '+'))\nprint(ক্যালকুলেটর(10, 5, '*'))\nprint(ক্যালকুলেটর(10, 0, '/'))\n","challenge":"ফাংশন বানান যা বলবে সংখ্যাটি মৌলিক কিনা।","expected_hint":"2 থেকে n-1 পর্যন্ত ভাগ যায় কিনা চেক করুন"},
    {"id":7,"title":"লিস্ট ও টাপল","title_en":"Lists & Tuples","category":"intermediate","icon":"📋","description":"একাধিক ডেটা একসাথে সংরক্ষণ","explanation":"<h3>লিস্ট</h3><pre><code>ফল = ['আম','কলা','লিচু']\nprint(ফল[0])  # আম\nফল.append('জাম')\nprint(len(ফল))</code></pre><h3>স্লাইসিং</h3><pre><code>সংখ্যা = [1,2,3,4,5]\nprint(সংখ্যা[1:3])  # [2,3]</code></pre><h3>লিস্ট কম্প্রিহেনশন</h3><pre><code>বর্গ = [x**2 for x in range(1,6)]\nprint(বর্গ)</code></pre>","starter_code":"নম্বর = [78, 92, 65, 88, 71, 95, 55, 83]\nprint('সর্বোচ্চ:', max(নম্বর))\nprint('সর্বনিম্ন:', min(নম্বর))\nprint('গড়:', sum(নম্বর)/len(নম্বর))\nপাস = [n for n in নম্বর if n >= 60]\nফেল = [n for n in নম্বর if n < 60]\nprint('পাস:', পাস)\nprint('ফেল:', ফেল)\n","challenge":"১০টি সংখ্যার লিস্ট থেকে জোড় ও বিজোড় আলাদা করুন।","expected_hint":"লিস্ট কম্প্রিহেনশন ব্যবহার করুন"},
    {"id":8,"title":"ডিকশনারি","title_en":"Dictionaries","category":"intermediate","icon":"📖","description":"key-value জোড়া দিয়ে ডেটা সংরক্ষণ","explanation":"<h3>ডিকশনারি</h3><pre><code>ছাত্র = {'নাম':'রহিম','বয়স':20}\nprint(ছাত্র['নাম'])</code></pre><h3>লুপ</h3><pre><code>for k, v in ছাত্র.items():\n    print(k, v)</code></pre><h3>get()</h3><pre><code>ফোন = ছাত্র.get('ফোন','নেই')\nprint(ফোন)</code></pre>","starter_code":"ছাত্র = {\n    'নাম': 'করিম',\n    'রোল': '001',\n    'নম্বর': {'বাংলা':80,'ইংরেজি':75,'গণিত':90}\n}\nprint('নাম:', ছাত্র['নাম'])\nনম্বর = ছাত্র['নম্বর']\nfor বিষয়, মান in নম্বর.items():\n    print(f'{বিষয়}: {মান}')\nprint('গড়:', sum(নম্বর.values())/len(নম্বর))\n","challenge":"৫টি দেশ ও রাজধানী ডিকশনারিতে রাখুন। দেশ জিজ্ঞেস করে রাজধানী বলুন।","expected_hint":"dict.get() ব্যবহার করুন"},
    {"id":9,"title":"ফাইল হ্যান্ডলিং","title_en":"File Handling","category":"intermediate","icon":"📁","description":"ফাইলে ডেটা লেখা ও পড়া","explanation":"<h3>ফাইলে লেখা</h3><pre><code>with open('নোট.txt','w',encoding='utf-8') as f:\n    f.write('পাইথন দিয়ে লেখা')</code></pre><h3>ফাইল পড়া</h3><pre><code>with open('নোট.txt','r',encoding='utf-8') as f:\n    print(f.read())</code></pre>","starter_code":"import os\nwith open('students.txt','w',encoding='utf-8') as f:\n    f.write('নাম,নম্বর\\n')\n    f.write('রহিম,85\\n')\n    f.write('করিম,92\\n')\nwith open('students.txt','r',encoding='utf-8') as f:\n    for line in f:\n        print(line.strip())\nos.remove('students.txt')\nprint('সম্পন্ন!')\n","challenge":"নাম ও নম্বর ইনপুট নিয়ে ফাইলে লিখুন ও পড়ুন।","expected_hint":"with open() ব্যবহার করুন"},
    {"id":10,"title":"ক্লাস ও অবজেক্ট","title_en":"Classes & OOP","category":"intermediate","icon":"🏗️","description":"অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিং","explanation":"<h3>ক্লাস</h3><pre><code>class ছাত্র:\n    def __init__(self, নাম):\n        self.নাম = নাম\n    def পরিচয়(self):\n        print(f'আমি {self.নাম}')\ns = ছাত্র('রহিম')\ns.পরিচয়()</code></pre><h3>ইনহেরিটেন্স</h3><pre><code>class শিক্ষক(ছাত্র):\n    def __init__(self, নাম, বিষয়):\n        super().__init__(নাম)\n        self.বিষয় = বিষয়</code></pre>","starter_code":"class ব্যাংক:\n    def __init__(self, মালিক, ব্যালেন্স=0):\n        self.মালিক = মালিক\n        self.ব্যালেন্স = ব্যালেন্স\n    def জমা(self, টাকা):\n        self.ব্যালেন্স += টাকা\n        print(f'{টাকা} জমা। ব্যালেন্স: {self.ব্যালেন্স}')\n    def তোলা(self, টাকা):\n        if টাকা <= self.ব্যালেন্স:\n            self.ব্যালেন্স -= টাকা\n            print(f'{টাকা} তোলা। ব্যালেন্স: {self.ব্যালেন্স}')\n        else:\n            print('অপর্যাপ্ত ব্যালেন্স!')\n\nac = ব্যাংক('রহিম', 1000)\nac.জমা(500)\nac.তোলা(200)\nac.তোলা(5000)\n","challenge":"Library ক্লাস বানান — বই যোগ, ইস্যু ও ফেরতের মেথড সহ।","expected_hint":"লিস্ট দিয়ে বইয়ের তালিকা রাখুন"}
]

@app.route('/')
def index():
    if 'completed' not in session:
        session['completed'] = []
    basic = [l for l in LESSONS if l['category']=='basic']
    intermediate = [l for l in LESSONS if l['category']=='intermediate']
    return render_template('index.html', basic=basic, intermediate=intermediate, completed=session.get('completed',[]), total=len(LESSONS))

@app.route('/lesson/<int:lid>')
def lesson(lid):
    l = next((x for x in LESSONS if x['id']==lid), None)
    if not l: return "পাঠ পাওয়া যায়নি", 404
    return render_template('lesson.html', lesson=l, completed=session.get('completed',[]), prev_lesson=lid-1 if lid>1 else None, next_lesson=lid+1 if lid<len(LESSONS) else None)

@app.route('/run', methods=['POST'])
def run_code():
    data = request.get_json()
    code = data.get('code','')
    user_input = data.get('input','')
    if not code.strip():
        return jsonify({'output':'','error':'কোড লিখুন!'})
    try:
        with tempfile.NamedTemporaryFile(mode='w',suffix='.py',delete=False,encoding='utf-8') as f:
            f.write(code)
            tmp = f.name
        result = subprocess.run([sys.executable,tmp],input=user_input,capture_output=True,text=True,timeout=10,encoding='utf-8')
        os.unlink(tmp)
        err = result.stderr.replace('Traceback (most recent call last):','⚠️ ত্রুটি:') if result.stderr else ''
        return jsonify({'output':result.stdout,'error':err})
    except subprocess.TimeoutExpired:
        return jsonify({'output':'','error':'⏱️ সময় শেষ! ১০ সেকেন্ডের বেশি চলতে পারবে না।'})
    except Exception as e:
        return jsonify({'output':'','error':str(e)})

@app.route('/complete/<int:lid>', methods=['POST'])
def complete(lid):
    if 'completed' not in session: session['completed']=[]
    c = list(session['completed'])
    if lid not in c: c.append(lid)
    session['completed']=c
    session.modified=True
    return jsonify({'success':True})

@app.route('/progress')
def progress():
    return jsonify({'completed':session.get('completed',[]),'total':len(LESSONS)})

if __name__=='__main__':
    app.run(debug=True)
